Skip to content

Commit edb879a

Browse files
SummedOp updates & optimization converters to use Opflow (qiskit-community/qiskit-aqua#1059)
* simplify and reduce, add equals to SummedOp, update tests * directly use new opflow, no need to go via WPO * update comments and docstrings * directly use opflow * don't do equality check in add * directly use opflow * change order in reduce * fix qaoa * add short test on summed op equality * rm prints * use set comparison, rename simplify to collapse_summands * fix expected value, should be sqrt(2), not 2 * cast coeffs to complex * add reno on equals * fix mypy * fix spell * fix lint * dont cast coefficient to complex leads to problems if the coeff is exponentitated and not supposed to be complex * use sum instead of reduce * rm unused import * move __hash__ to primitive op and base on repr * use != over not == * add summed op test for different primitives * check for opbase, not summedop * adress changes from review * explicitly raise an error upon ListOp input * return identity op instead of the int 0 * fix spell * add note that equals is not mathematically sound Co-authored-by: Manoel Marques <[email protected]>
1 parent 1682fc0 commit edb879a

File tree

5 files changed

+102
-141
lines changed

5 files changed

+102
-141
lines changed

qiskit/optimization/converters/ising_to_quadratic_program.py

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515

1616
"""The converter from a ```Operator``` to ``QuadraticProgram``."""
1717

18-
from typing import Optional
18+
from typing import Optional, Union
1919
import copy
2020

2121
import numpy as np
2222

23-
from qiskit.aqua.operators.legacy import WeightedPauliOperator
23+
from qiskit.aqua.operators import OperatorBase, WeightedPauliOperator, SummedOp, ListOp
2424
from ..problems.quadratic_program import QuadraticProgram
2525
from ..exceptions import QiskitOptimizationError
2626

@@ -44,7 +44,8 @@ def __init__(self, linear: bool = False) -> None:
4444
self._qp = None # type: Optional[QuadraticProgram]
4545
self._linear = linear
4646

47-
def encode(self, qubit_op: WeightedPauliOperator, offset: float = 0.0) -> QuadraticProgram:
47+
def encode(self, qubit_op: Union[OperatorBase, WeightedPauliOperator], offset: float = 0.0
48+
) -> QuadraticProgram:
4849
"""Convert a qubit operator and a shift value into a quadratic program
4950
5051
Args:
@@ -58,8 +59,18 @@ def encode(self, qubit_op: WeightedPauliOperator, offset: float = 0.0) -> Quadra
5859
Raises:
5960
QiskitOptimizationError: If there are Pauli Xs in any Pauli term
6061
QiskitOptimizationError: If there are more than 2 Pauli Zs in any Pauli term
62+
NotImplementedError: If the input operator is a ListOp
6163
"""
6264
# Set properties
65+
if isinstance(qubit_op, WeightedPauliOperator):
66+
qubit_op = qubit_op.to_opflow()
67+
68+
# No support for ListOp yet, this can be added in future
69+
# pylint: disable=unidiomatic-typecheck
70+
if type(qubit_op) == ListOp:
71+
raise NotImplementedError('Conversion of a ListOp is not supported, convert each '
72+
'operator in the ListOp separately.')
73+
6374
self._qubit_op = qubit_op
6475
self._offset = copy.deepcopy(offset)
6576
self._num_qubits = qubit_op.num_qubits
@@ -134,24 +145,31 @@ def _create_qubo_matrix(self):
134145
# The other elements in the QUBO matrix is for quadratic terms of the qubit operator
135146
self._qubo_matrix = np.zeros((self._num_qubits, self._num_qubits))
136147

137-
for pauli in self._qubit_op.paulis:
148+
if not isinstance(self._qubit_op, SummedOp):
149+
oplist = [self._qubit_op.to_pauli_op()]
150+
else:
151+
oplist = self._qubit_op.to_pauli_op().oplist
152+
153+
for pauli_op in oplist:
154+
pauli = pauli_op.primitive
155+
coeff = pauli_op.coeff
138156
# Count the number of Pauli Zs in a Pauli term
139-
lst_z = pauli[1].z.tolist()
157+
lst_z = pauli.z.tolist()
140158
z_index = [i for i, z in enumerate(lst_z) if z is True]
141159
num_z = len(z_index)
142160

143161
# Add its weight of the Pauli term to the corresponding element of QUBO matrix
144162
if num_z == 1:
145-
self._qubo_matrix[z_index[0], z_index[0]] = pauli[0].real
163+
self._qubo_matrix[z_index[0], z_index[0]] = coeff.real
146164
elif num_z == 2:
147-
self._qubo_matrix[z_index[0], z_index[1]] = pauli[0].real
165+
self._qubo_matrix[z_index[0], z_index[1]] = coeff.real
148166
else:
149167
raise QiskitOptimizationError(
150-
'There are more than 2 Pauli Zs in the Pauli term {}'.format(pauli[1].z)
168+
'There are more than 2 Pauli Zs in the Pauli term {}'.format(pauli.z)
151169
)
152170

153171
# If there are Pauli Xs in the Pauli term, raise an error
154-
lst_x = pauli[1].x.tolist()
172+
lst_x = pauli.x.tolist()
155173
x_index = [i for i, x in enumerate(lst_x) if x is True]
156174
if len(x_index) > 0:
157-
raise QiskitOptimizationError('Pauli Xs exist in the Pauli {}'.format(pauli[1].x))
175+
raise QiskitOptimizationError('Pauli Xs exist in the Pauli {}'.format(pauli.x))

qiskit/optimization/converters/quadratic_program_to_ising.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import numpy as np
2121
from qiskit.quantum_info import Pauli
2222

23-
from qiskit.aqua.operators import WeightedPauliOperator
23+
from qiskit.aqua.operators import OperatorBase, PauliOp, I
2424

2525
from ..problems.quadratic_program import QuadraticProgram
2626
from ..exceptions import QiskitOptimizationError
@@ -33,7 +33,7 @@ def __init__(self) -> None:
3333
"""Initialize the internal data structure."""
3434
self._src = None # type: Optional[QuadraticProgram]
3535

36-
def encode(self, op: QuadraticProgram) -> Tuple[WeightedPauliOperator, float]:
36+
def encode(self, op: QuadraticProgram) -> Tuple[OperatorBase, float]:
3737
"""Convert a problem into a qubit operator
3838
3939
Args:
@@ -114,6 +114,13 @@ def encode(self, op: QuadraticProgram) -> Tuple[WeightedPauliOperator, float]:
114114
shift += weight
115115

116116
# Remove paulis whose coefficients are zeros.
117-
qubit_op = WeightedPauliOperator(paulis=pauli_list)
117+
qubit_op = sum(PauliOp(pauli, coeff=coeff) for coeff, pauli in pauli_list)
118+
119+
# qubit_op could be the integer 0, in this case return an identity operator of
120+
# appropriate size
121+
if isinstance(qubit_op, OperatorBase):
122+
qubit_op = qubit_op.reduce()
123+
else:
124+
qubit_op = I ^ num_nodes
118125

119126
return qubit_op, shift

test/optimization/test_converters.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import numpy as np
2121
from docplex.mp.model import Model
2222

23-
from qiskit.aqua.operators import WeightedPauliOperator
23+
from qiskit.aqua.operators import Z, I
2424
from qiskit.aqua.algorithms import NumPyMinimumEigensolver
2525
from qiskit.optimization import QuadraticProgram, QiskitOptimizationError
2626
from qiskit.optimization.problems import Constraint, Variable
@@ -34,25 +34,19 @@
3434
)
3535
from qiskit.optimization.algorithms import MinimumEigenOptimizer, CplexOptimizer, ADMMOptimizer
3636
from qiskit.optimization.algorithms.admm_optimizer import ADMMParameters
37-
from qiskit.quantum_info import Pauli
3837

3938
logger = logging.getLogger(__name__)
4039

41-
42-
QUBIT_OP_MAXIMIZE_SAMPLE = WeightedPauliOperator(
43-
paulis=[
44-
[(-199999.5 + 0j), Pauli(z=[True, False, False, False], x=[False, False, False, False])],
45-
[(-399999.5 + 0j), Pauli(z=[False, True, False, False], x=[False, False, False, False])],
46-
[(-599999.5 + 0j), Pauli(z=[False, False, True, False], x=[False, False, False, False])],
47-
[(-799999.5 + 0j), Pauli(z=[False, False, False, True], x=[False, False, False, False])],
48-
[(100000 + 0j), Pauli(z=[True, True, False, False], x=[False, False, False, False])],
49-
[(150000 + 0j), Pauli(z=[True, False, True, False], x=[False, False, False, False])],
50-
[(300000 + 0j), Pauli(z=[False, True, True, False], x=[False, False, False, False])],
51-
[(200000 + 0j), Pauli(z=[True, False, False, True], x=[False, False, False, False])],
52-
[(400000 + 0j), Pauli(z=[False, True, False, True], x=[False, False, False, False])],
53-
[(600000 + 0j), Pauli(z=[False, False, True, True], x=[False, False, False, False])],
54-
]
55-
)
40+
QUBIT_OP_MAXIMIZE_SAMPLE = -199999.5 * (I ^ I ^ I ^ Z) + \
41+
-399999.5 * (I ^ I ^ Z ^ I) + \
42+
-599999.5 * (I ^ Z ^ I ^ I) + \
43+
-799999.5 * (Z ^ I ^ I ^ I) + \
44+
100000 * (I ^ I ^ Z ^ Z) + \
45+
150000 * (I ^ Z ^ I ^ Z) + \
46+
300000 * (I ^ Z ^ Z ^ I) + \
47+
200000 * (Z ^ I ^ I ^ Z) + \
48+
400000 * (Z ^ I ^ Z ^ I) + \
49+
600000 * (Z ^ Z ^ I ^ I)
5650
OFFSET_MAXIMIZE_SAMPLE = 1149998
5751

5852

@@ -432,12 +426,7 @@ def test_optimizationproblem_to_ising(self):
432426
op2 = penalize.encode(op)
433427
qubitop, offset = op2ope.encode(op2)
434428

435-
# the encoder uses a dictionary, in which the order of items in Python 3.5 is not
436-
# maintained, therefore don't do a list compare but dictionary compare
437-
qubit_op_as_dict = dict(qubitop.paulis)
438-
for coeff, paulis in QUBIT_OP_MAXIMIZE_SAMPLE.paulis:
439-
self.assertEqual(paulis, qubit_op_as_dict[coeff])
440-
429+
self.assertEqual(qubitop, QUBIT_OP_MAXIMIZE_SAMPLE)
441430
self.assertEqual(offset, OFFSET_MAXIMIZE_SAMPLE)
442431

443432
def test_ising_to_quadraticprogram_linear(self):

test/optimization/test_docplex.py

Lines changed: 50 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -21,112 +21,63 @@
2121
import networkx as nx
2222
import numpy as np
2323
from docplex.mp.model import Model
24-
from qiskit.quantum_info import Pauli
2524

2625
from qiskit.aqua import AquaError, aqua_globals
2726
from qiskit.aqua.algorithms import NumPyMinimumEigensolver
2827
from qiskit.optimization.applications.ising import docplex, tsp
29-
from qiskit.aqua.operators import WeightedPauliOperator
28+
from qiskit.aqua.operators import I, Z
3029

3130
# Reference operators and offsets for maxcut and tsp.
32-
QUBIT_OP_MAXCUT = WeightedPauliOperator(
33-
paulis=[[0.5, Pauli(z=[True, True, False, False], x=[False, False, False, False])],
34-
[0.5, Pauli(z=[True, False, True, False], x=[False, False, False, False])],
35-
[0.5, Pauli(z=[False, True, True, False], x=[False, False, False, False])],
36-
[0.5, Pauli(z=[True, False, False, True], x=[False, False, False, False])],
37-
[0.5, Pauli(z=[False, False, True, True], x=[False, False, False, False])]])
31+
QUBIT_OP_MAXCUT = 0.5 * ((I ^ I ^ Z ^ Z) + (I ^ Z ^ I ^ Z) + (I ^ Z ^ Z ^ I) + (Z ^ I ^ I ^ Z)
32+
+ (Z ^ Z ^ I ^ I))
3833
OFFSET_MAXCUT = -2.5
39-
QUBIT_OP_TSP = WeightedPauliOperator(
40-
paulis=[[-100057.0, Pauli(z=[True, False, False, False, False, False, False, False, False],
41-
x=[False, False, False, False, False, False, False, False, False])],
42-
[-100071.0, Pauli(z=[False, False, False, False, True, False, False, False, False],
43-
x=[False, False, False, False, False, False, False, False, False])],
44-
[14.5, Pauli(z=[True, False, False, False, True, False, False, False, False],
45-
x=[False, False, False, False, False, False, False, False, False])],
46-
[-100057.0, Pauli(z=[False, True, False, False, False, False, False, False, False],
47-
x=[False, False, False, False, False, False, False, False, False])],
48-
[-100071.0, Pauli(z=[False, False, False, False, False, True, False, False, False],
49-
x=[False, False, False, False, False, False, False, False, False])],
50-
[14.5, Pauli(z=[False, True, False, False, False, True, False, False, False],
51-
x=[False, False, False, False, False, False, False, False, False])],
52-
[-100057.0, Pauli(z=[False, False, True, False, False, False, False, False, False],
53-
x=[False, False, False, False, False, False, False, False, False])],
54-
[-100071.0, Pauli(z=[False, False, False, True, False, False, False, False, False],
55-
x=[False, False, False, False, False, False, False, False, False])],
56-
[14.5, Pauli(z=[False, False, True, True, False, False, False, False, False],
57-
x=[False, False, False, False, False, False, False, False, False])],
58-
[-100070.0, Pauli(z=[False, False, False, False, False, False, False, True, False],
59-
x=[False, False, False, False, False, False, False, False, False])],
60-
[14.0, Pauli(z=[True, False, False, False, False, False, False, True, False],
61-
x=[False, False, False, False, False, False, False, False, False])],
62-
[-100070.0, Pauli(z=[False, False, False, False, False, False, False, False, True],
63-
x=[False, False, False, False, False, False, False, False, False])],
64-
[14.0, Pauli(z=[False, True, False, False, False, False, False, False, True],
65-
x=[False, False, False, False, False, False, False, False, False])],
66-
[-100070.0, Pauli(z=[False, False, False, False, False, False, True, False, False],
67-
x=[False, False, False, False, False, False, False, False, False])],
68-
[14.0, Pauli(z=[False, False, True, False, False, False, True, False, False],
69-
x=[False, False, False, False, False, False, False, False, False])],
70-
[14.5, Pauli(z=[False, True, False, True, False, False, False, False, False],
71-
x=[False, False, False, False, False, False, False, False, False])],
72-
[14.5, Pauli(z=[False, False, True, False, True, False, False, False, False],
73-
x=[False, False, False, False, False, False, False, False, False])],
74-
[14.5, Pauli(z=[True, False, False, False, False, True, False, False, False],
75-
x=[False, False, False, False, False, False, False, False, False])],
76-
[21.0, Pauli(z=[False, False, False, True, False, False, False, True, False],
77-
x=[False, False, False, False, False, False, False, False, False])],
78-
[21.0, Pauli(z=[False, False, False, False, True, False, False, False, True],
79-
x=[False, False, False, False, False, False, False, False, False])],
80-
[21.0, Pauli(z=[False, False, False, False, False, True, True, False, False],
81-
x=[False, False, False, False, False, False, False, False, False])],
82-
[14.0, Pauli(z=[False, True, False, False, False, False, True, False, False],
83-
x=[False, False, False, False, False, False, False, False, False])],
84-
[14.0, Pauli(z=[False, False, True, False, False, False, False, True, False],
85-
x=[False, False, False, False, False, False, False, False, False])],
86-
[14.0, Pauli(z=[True, False, False, False, False, False, False, False, True],
87-
x=[False, False, False, False, False, False, False, False, False])],
88-
[21.0, Pauli(z=[False, False, False, False, True, False, True, False, False],
89-
x=[False, False, False, False, False, False, False, False, False])],
90-
[21.0, Pauli(z=[False, False, False, False, False, True, False, True, False],
91-
x=[False, False, False, False, False, False, False, False, False])],
92-
[21.0, Pauli(z=[False, False, False, True, False, False, False, False, True],
93-
x=[False, False, False, False, False, False, False, False, False])],
94-
[50000.0, Pauli(z=[True, False, False, True, False, False, False, False, False],
95-
x=[False, False, False, False, False, False, False, False, False])],
96-
[50000.0, Pauli(z=[True, False, False, False, False, False, True, False, False],
97-
x=[False, False, False, False, False, False, False, False, False])],
98-
[50000.0, Pauli(z=[False, False, False, True, False, False, True, False, False],
99-
x=[False, False, False, False, False, False, False, False, False])],
100-
[50000.0, Pauli(z=[False, True, False, False, True, False, False, False, False],
101-
x=[False, False, False, False, False, False, False, False, False])],
102-
[50000.0, Pauli(z=[False, True, False, False, False, False, False, True, False],
103-
x=[False, False, False, False, False, False, False, False, False])],
104-
[50000.0, Pauli(z=[False, False, False, False, True, False, False, True, False],
105-
x=[False, False, False, False, False, False, False, False, False])],
106-
[50000.0, Pauli(z=[False, False, True, False, False, True, False, False, False],
107-
x=[False, False, False, False, False, False, False, False, False])],
108-
[50000.0, Pauli(z=[False, False, True, False, False, False, False, False, True],
109-
x=[False, False, False, False, False, False, False, False, False])],
110-
[50000.0, Pauli(z=[False, False, False, False, False, True, False, False, True],
111-
x=[False, False, False, False, False, False, False, False, False])],
112-
[50000.0, Pauli(z=[True, True, False, False, False, False, False, False, False],
113-
x=[False, False, False, False, False, False, False, False, False])],
114-
[50000.0, Pauli(z=[True, False, True, False, False, False, False, False, False],
115-
x=[False, False, False, False, False, False, False, False, False])],
116-
[50000.0, Pauli(z=[False, True, True, False, False, False, False, False, False],
117-
x=[False, False, False, False, False, False, False, False, False])],
118-
[50000.0, Pauli(z=[False, False, False, True, True, False, False, False, False],
119-
x=[False, False, False, False, False, False, False, False, False])],
120-
[50000.0, Pauli(z=[False, False, False, True, False, True, False, False, False],
121-
x=[False, False, False, False, False, False, False, False, False])],
122-
[50000.0, Pauli(z=[False, False, False, False, True, True, False, False, False],
123-
x=[False, False, False, False, False, False, False, False, False])],
124-
[50000.0, Pauli(z=[False, False, False, False, False, False, True, True, False],
125-
x=[False, False, False, False, False, False, False, False, False])],
126-
[50000.0, Pauli(z=[False, False, False, False, False, False, True, False, True],
127-
x=[False, False, False, False, False, False, False, False, False])],
128-
[50000.0, Pauli(z=[False, False, False, False, False, False, False, True, True],
129-
x=[False, False, False, False, False, False, False, False, False])]])
34+
QUBIT_OP_TSP = (
35+
-100057.0 * (I ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ Z) +
36+
-100071.0 * (I ^ I ^ I ^ I ^ Z ^ I ^ I ^ I ^ I) +
37+
14.5 * (I ^ I ^ I ^ I ^ Z ^ I ^ I ^ I ^ Z) +
38+
-100057.0 * (I ^ I ^ I ^ I ^ I ^ I ^ I ^ Z ^ I) +
39+
-100071.0 * (I ^ I ^ I ^ Z ^ I ^ I ^ I ^ I ^ I) +
40+
14.5 * (I ^ I ^ I ^ Z ^ I ^ I ^ I ^ Z ^ I) +
41+
-100057.0 * (I ^ I ^ I ^ I ^ I ^ I ^ Z ^ I ^ I) +
42+
-100071.0 * (I ^ I ^ I ^ I ^ I ^ Z ^ I ^ I ^ I) +
43+
14.5 * (I ^ I ^ I ^ I ^ I ^ Z ^ Z ^ I ^ I) +
44+
-100070.0 * (I ^ Z ^ I ^ I ^ I ^ I ^ I ^ I ^ I) +
45+
14.0 * (I ^ Z ^ I ^ I ^ I ^ I ^ I ^ I ^ Z) +
46+
-100070.0 * (Z ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ I) +
47+
14.0 * (Z ^ I ^ I ^ I ^ I ^ I ^ I ^ Z ^ I) +
48+
-100070.0 * (I ^ I ^ Z ^ I ^ I ^ I ^ I ^ I ^ I) +
49+
14.0 * (I ^ I ^ Z ^ I ^ I ^ I ^ Z ^ I ^ I) +
50+
14.5 * (I ^ I ^ I ^ I ^ I ^ Z ^ I ^ Z ^ I) +
51+
14.5 * (I ^ I ^ I ^ I ^ Z ^ I ^ Z ^ I ^ I) +
52+
14.5 * (I ^ I ^ I ^ Z ^ I ^ I ^ I ^ I ^ Z) +
53+
21.0 * (I ^ Z ^ I ^ I ^ I ^ Z ^ I ^ I ^ I) +
54+
21.0 * (Z ^ I ^ I ^ I ^ Z ^ I ^ I ^ I ^ I) +
55+
21.0 * (I ^ I ^ Z ^ Z ^ I ^ I ^ I ^ I ^ I) +
56+
14.0 * (I ^ I ^ Z ^ I ^ I ^ I ^ I ^ Z ^ I) +
57+
14.0 * (I ^ Z ^ I ^ I ^ I ^ I ^ Z ^ I ^ I) +
58+
14.0 * (Z ^ I ^ I ^ I ^ I ^ I ^ I ^ I ^ Z) +
59+
21.0 * (I ^ I ^ Z ^ I ^ Z ^ I ^ I ^ I ^ I) +
60+
21.0 * (I ^ Z ^ I ^ Z ^ I ^ I ^ I ^ I ^ I) +
61+
21.0 * (Z ^ I ^ I ^ I ^ I ^ Z ^ I ^ I ^ I) +
62+
50000.0 * (I ^ I ^ I ^ I ^ I ^ Z ^ I ^ I ^ Z) +
63+
50000.0 * (I ^ I ^ Z ^ I ^ I ^ I ^ I ^ I ^ Z) +
64+
50000.0 * (I ^ I ^ Z ^ I ^ I ^ Z ^ I ^ I ^ I) +
65+
50000.0 * (I ^ I ^ I ^ I ^ Z ^ I ^ I ^ Z ^ I) +
66+
50000.0 * (I ^ Z ^ I ^ I ^ I ^ I ^ I ^ Z ^ I) +
67+
50000.0 * (I ^ Z ^ I ^ I ^ Z ^ I ^ I ^ I ^ I) +
68+
50000.0 * (I ^ I ^ I ^ Z ^ I ^ I ^ Z ^ I ^ I) +
69+
50000.0 * (Z ^ I ^ I ^ I ^ I ^ I ^ Z ^ I ^ I) +
70+
50000.0 * (Z ^ I ^ I ^ Z ^ I ^ I ^ I ^ I ^ I) +
71+
50000.0 * (I ^ I ^ I ^ I ^ I ^ I ^ I ^ Z ^ Z) +
72+
50000.0 * (I ^ I ^ I ^ I ^ I ^ I ^ Z ^ I ^ Z) +
73+
50000.0 * (I ^ I ^ I ^ I ^ I ^ I ^ Z ^ Z ^ I) +
74+
50000.0 * (I ^ I ^ I ^ I ^ Z ^ Z ^ I ^ I ^ I) +
75+
50000.0 * (I ^ I ^ I ^ Z ^ I ^ Z ^ I ^ I ^ I) +
76+
50000.0 * (I ^ I ^ I ^ Z ^ Z ^ I ^ I ^ I ^ I) +
77+
50000.0 * (I ^ Z ^ Z ^ I ^ I ^ I ^ I ^ I ^ I) +
78+
50000.0 * (Z ^ I ^ Z ^ I ^ I ^ I ^ I ^ I ^ I) +
79+
50000.0 * (Z ^ Z ^ I ^ I ^ I ^ I ^ I ^ I ^ I)
80+
)
13081
OFFSET_TSP = 600279.0
13182

13283

0 commit comments

Comments
 (0)