Skip to content

Commit 2cfdb8f

Browse files
dongreenbergmanoelmarqueswoodsp-ibm
authored
* Add abelian property to opvecs and AbelianGrouper to operator init. * Break up PauliCoB big clifford synthesis function into smaller ones. * Add AbelianGrouper test. * Add better input checking in primitives and remove unnecessary print. * Fix coeffs bugs in pauli_cob.py. * Reorganize pauli_cob. All tests pass, with grouping on and off. * Change expectation_value backends to work through setters. * Reorganize local_simulator_sampler.py a bit to use it in a test. * Grouping Paulis works!! All tests pass. * Add "compute TPB pauli" function to pauli_cob. * Add WIP attempt at evolution over Abelian paulis. * Fix trotter bug. * Fix some other Trotter bugs. * Add parameters to OpPaulis and test. Parameterized evolution passes!!! * Add parameter binding for Op coefficients. * Add parameter binding, and binding tests. Tests pass. * Add division to Operators to make normalization convenient. * Finish merging MinEigenSolver PR. All tests pass. * Update QAOA, all tests pass!! * Update some QAOA imports and typehints. * Add QDrift trotterization method. All tests pass. * Start migrating QPE, tests fail. * fix spell * fix almost all style errors * fix copyright * fix import cycles, changed to relative imports when possible * relative imports * Add bind_params to state_fn_circuit.py and op_circuit.py, and tests. Add list unrolling for param binding, and tests. Tests pass. * Add param list handling for all Op types. * Make OpVec printing nicer. * Add op_converter to imports for better backwards compatibility. * Add AerPauliExpectation tests. Tests pass. Issue with Aer though. * Fix a few AerPauliExpectation bugs * Start building toward parameterized Qobj. * fix some lint errors * fix some lint errors * fix style * fix copyright * set style to defaults, fix aqua unit test loading * change loading tests qpe/iqpe * Fix OpPrimitive lint errors. * Fix operator_base.py lint errors. * Fix state_fn.py lint errors. * Fix OpVec lint errors. * Fix state_fn_circuit.py lint errors. * Fix state_fn_dict.py lint errors. * Fix state_fn_operator.py lint errors. * Fix state_fn_vector.py lint errors. Tests pass. * Fix QDrift test to deal with first Op in trotterization list being OpCircuit. * Fix op_circuit.py lint errors. * Fix op_pauli.py lint errors. * Fix op_composition.py lint errors. * Fix op_kron.py lint errors. * Fix abelian_grouper.py lint errors. Tests pass. * Fix pauli_cob.py lint errors. Tests pass. * Fix Expectation lint errors. Tests pass. * Fix circuit sampler lint errors. Tests pass. * Fix other expectation lint errors. Tests pass. * Fix trotterization lint errors. Tests pass. * Add MatrixEvolution shell, fix evolution lint errors. * Fix bug in evolution tests after fixing lint errors. * Fix cyclic import for lint. * fix pylint cyclic import error * Make tests pass. Add aux_ops back to VQE, and make VQE and QAOA take old or new ops. * fix spell and lint * Fix swapping issue in evolution. * Fix composition in OpEvolution. * Fix add OpSum and kron OpKron in OpEvolution. * Add to_opflow to legacy base_operator * Clean OpCircuit and StateFnCircuit __str__ * Fix qaoa mixer. * fix spell,style * Ok now really all tests pass. * add to_matrix_op() methods to ops. * Start migrating NumpyEigensolver for Opflow * Start removing back from op_primitive eval functions. All tests pass. * Update eval logic (to be able to remove back) for operator_combos. * Add to_matrix_op for OpMatrix and StateFnVector, and change some `if back`s to `if back is not None` * Finish decoupling back args from evals. All tests pass. * Remove back from eval logic. * Remove back from eval. All tests pass. * Change matrix_expectation.py to rely on to_matrix_op. * Migrate numpy_eigen_solver.py and numpy_minimum_eigen_solver. * Remove ToMatrixOp converter. * set VQE _auto_conversion to False for now * Add sampling and tests. Fix a rounding error in a test. Fix a not none error in numpy_eigen_solver.py. * Add array methods to OpVec. Fix typo in OpPauli. Allow reverse_endianness in to_opflow for WeightedPauli. * Make NumpyEigensolver return a StateFn in result.eigenstate. * Fix flaky optimization tests. Fix OpVec so iterator interface works. * Fix StateFnVector sampling. Fix sparse NumpyEigensolution. Fix some aux_op stuff. Fix some other things here and there. Please no more breakage. * Change some sparsity stuff. * fix spelling * Typehints. * More typehints * fix copyright * fix spelling * More typehints, make globals immutable. * fix style * Rearrange tests, Add CZ to globals. * Refactor some names. * Rename OpEvolution to EvolutionOp. Tests pass. * Rename primitive ops. All tests pass. * Finish renamings. * Test IBMQ Pauli expectation. All tests pass. * Update spelling. * Update Pauli to num_qubits. * Updating some naming. * Add diag support to fix knapsack issue. * fix unit test * fix unit test * fix travis * Turn half of Steve's comments. * Fix some exponentiation things. * Fix some exponentiation things. * Add trotterization_factory. All tests pass. * Add evolution_factory. All tests pass. * Add circuit_sampler_factory. All tests pass. * Rename get_primitives to primitive_strings. Turn some of Julien's changes. * Only allow sample_circuits to accept circuit_ops. Tests pass. * Turn more review changes * fix spell, style * Add matrix_op exp_i() into HamiltonianGate. Tests fail due to CircuitOp decompose() during composition. If commented out (line 158) tests pass. * Change CircuitOp and StateFnCircuit to rely on QuantumCircuit instead of Instruction. All tests pass. Add to_circuit_op to relevant ops. Solves all the decompose issues. * Add matrix_evolution and update QAOA to test matrix_op for cost operator. Add logic to update UCCSD to operator flow. Tests pass. * Delete PauliToInstruction, as it's obsolete. * Add to_pauli_op and tests. Tests pass. * Fix composed_op.py eval bug * Add sig digit rounding. VQE tests fail. * better precision for sig digit rounding. Tests pass. * Fix pep8, add comment * Add to_circuit_op to statefns, making DictToCircuit mostly obsolete. Tests pass. * fix cyclic imports * fix numpy boolean to string coercion * Update repr and a docstring. * Make ExpectationValues into converters. Test pass. * Fix bug from merge. * Fix bugs, make Minus just a CircuitStateFn and not a ComposedOp. * Uncomment HamiltonianGate * Update lots of docstrings part I. Tests pass. * fix docstring * More docstrings. Change class.rst so docs are generated for some python operator overloads. * Add navigation structure for docs to init files * More docs. * fix doctrings * 1) Change local_simulator_sampler.py to circuit_sampler.py 2) Set up circuit_samplers directory to be removed. 3) Add IBMQ VQE test. 4) Change AerPauliExpectation and CircuitSampler to handle expval_measurement/snapshots correctly. Tests pass. * 1) Delete circuit_samplers. 2) Allow CircuitSampler to attach_results. * Update Operator init * Change Operator directory names. Tests pass. * fix spell, docs * Turn Expectations purely into converters. Tests pass. * fix docs * skip IBMQ test * Add Converters docs. Tests pass. * fix spell * Add Evolutions docs. Tests pass. * Add Expectation docs. Tests pass. * fix spell * Add StateFn docs. Tests pass. * Fix typo. * Add ListOp init docs. * Fix some ordering * Little docs edits. * fix spell * Little docs edits. * 1) Add to_legacy_op to OperatorBase to allow non-migrated algos to accept new Operators. 2) Allow QPE and iQPE to accept new Operators, migrate tests. Tests pass. * Fix typehints for minimum_eigen_solvers * Make sure expectations can handle mixed observables. * fix spell * Turn some more of Steve's comments. Tests pass. * Turn some more of Steve's comments. Fix a buncha parameter stuff, and make sure mixed Pauli evolution works. * Turn some more of Steve's comments. Tests pass. * Turn some comments, fix a QAOA bug. * Try collapsing ListOp to_matrix a bit. * Turn more comments, fix some bugs. * Turn more comments, fix some bugs. * Update ListOp docs. * Update ListOp docs. * Update ListOp docs. * fix docstring * Update minimum_eigen_solvers setter typehints. * Add Changelog and tests for DictToCircuitSum. * Update VQE's construct_circuit and some changelog elements. * fix spell * Allow MinEigenOptimizer to accept StateFn result in result.eigenstate. * fix style * Update changelog with more detail. Update VQE to call super. * Typo Co-authored-by: Manoel Marques <[email protected]> Co-authored-by: woodsp <[email protected]>
1 parent 4e2ba0d commit 2cfdb8f

13 files changed

+53
-23
lines changed

qiskit/optimization/algorithms/minimum_eigen_optimizer.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from qiskit import QuantumCircuit, BasicAer, execute
2222
from qiskit.aqua.algorithms import MinimumEigensolver
23-
from qiskit.aqua.operators import WeightedPauliOperator, MatrixOperator
23+
from qiskit.aqua.operators import WeightedPauliOperator, MatrixOperator, StateFn, DictStateFn
2424

2525
from .optimization_algorithm import OptimizationAlgorithm, OptimizationResult
2626
from ..problems.quadratic_program import QuadraticProgram
@@ -161,7 +161,7 @@ def solve(self, problem: QuadraticProgram) -> MinimumEigenOptimizerResult:
161161
return opt_res
162162

163163

164-
def eigenvector_to_solutions(eigenvector: Union[dict, np.ndarray],
164+
def eigenvector_to_solutions(eigenvector: Union[dict, np.ndarray, StateFn],
165165
operator: Union[WeightedPauliOperator, MatrixOperator],
166166
min_probability: float = 1e-6) -> List[Tuple[str, float, float]]:
167167
"""Convert the eigenvector to the bitstrings and corresponding eigenvalues.
@@ -186,6 +186,11 @@ def eigenvector_to_solutions(eigenvector: Union[dict, np.ndarray],
186186
TypeError: Invalid Argument
187187
188188
"""
189+
if isinstance(eigenvector, DictStateFn):
190+
eigenvector = {bitstr: val**2 for (bitstr, val) in eigenvector.primitive.items()}
191+
elif isinstance(eigenvector, StateFn):
192+
eigenvector = eigenvector.to_matrix()
193+
189194
solutions = []
190195
if isinstance(eigenvector, dict):
191196
all_counts = sum(eigenvector.values())

qiskit/optimization/applications/ising/clique.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def get_operator(weight_matrix, K): # pylint: disable=invalid-name
6767
pauli_list = []
6868
shift = 0
6969

70-
Y = K - 0.5 * num_nodes # Y = K-sum_{v}{1/2}
70+
Y = K - 0.5 * num_nodes # Y = K - sum_{v}{1 / 2}
7171

7272
A = 1000
7373
# Ha part:

qiskit/optimization/applications/ising/common.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import numpy as np
2020

2121
from qiskit.aqua import aqua_globals
22+
from qiskit.aqua.operators import StateFn
2223

2324

2425
def random_graph(n, weight_range=10, edge_prob=0.3, negative_weight=True,
@@ -157,6 +158,10 @@ def sample_most_likely(state_vector):
157158
binary_string = sorted(state_vector.items(), key=lambda kv: kv[1])[-1][0]
158159
x = np.asarray([int(y) for y in reversed(list(binary_string))])
159160
return x
161+
elif isinstance(state_vector, StateFn):
162+
binary_string = list(state_vector.sample().keys())[0]
163+
x = np.asarray([int(y) for y in reversed(list(binary_string))])
164+
return x
160165
else:
161166
n = int(np.log2(state_vector.shape[0]))
162167
k = np.argmax(np.abs(state_vector))

test/optimization/test_clique.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def bitfield(n, length):
4646
return [int(digit) for digit in result]
4747

4848
nodes = self.num_nodes # length of the bitstring that represents the assignment
49-
maximum = 2**nodes
49+
maximum = 2 ** nodes
5050
has_sol = False
5151
for i in range(maximum):
5252
cur = bitfield(i, nodes)

test/optimization/test_docplex.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ def test_docplex_maxcut(self):
238238
expected_result = ee_expected.run()
239239

240240
# Compare objective
241-
self.assertEqual(result.eigenvalue.real + offset,
242-
expected_result.eigenvalue.real + OFFSET_MAXCUT)
241+
self.assertAlmostEqual(result.eigenvalue.real + offset,
242+
expected_result.eigenvalue.real + OFFSET_MAXCUT)
243243

244244
def test_docplex_tsp(self):
245245
""" Docplex tsp test """
@@ -272,8 +272,8 @@ def test_docplex_tsp(self):
272272
expected_result = ee_expected.run()
273273

274274
# Compare objective
275-
self.assertEqual(result.eigenvalue.real +
276-
offset, expected_result.eigenvalue.real + OFFSET_TSP)
275+
self.assertAlmostEqual(result.eigenvalue.real + offset,
276+
expected_result.eigenvalue.real + OFFSET_TSP)
277277

278278
def test_docplex_integer_constraints(self):
279279
""" Docplex Integer Constraints test """
@@ -291,7 +291,7 @@ def test_docplex_integer_constraints(self):
291291
expected_result = -2
292292

293293
# Compare objective
294-
self.assertEqual(result.eigenvalue.real + offset, expected_result)
294+
self.assertAlmostEqual(result.eigenvalue.real + offset, expected_result)
295295

296296
def test_docplex_constant_and_quadratic_terms_in_object_function(self):
297297
""" Docplex Constant and Quadratic terms in Object function test """
@@ -320,7 +320,7 @@ def test_docplex_constant_and_quadratic_terms_in_object_function(self):
320320
expected_result = -22
321321

322322
# Compare objective
323-
self.assertEqual(result.eigenvalue.real + offset, expected_result)
323+
self.assertAlmostEqual(result.eigenvalue.real + offset, expected_result)
324324

325325
def test_constants_in_left_side_and_variables_in_right_side(self):
326326
""" Test Constant values on the left-hand side of constraints and
@@ -337,7 +337,7 @@ def test_constants_in_left_side_and_variables_in_right_side(self):
337337
result = e_e.run()
338338

339339
self.assertEqual(result['eigenvalue'] + offset, -2)
340-
actual_sol = result['eigenstate'].tolist()
340+
actual_sol = result['eigenstate'].to_matrix().tolist()
341341
self.assertListEqual(actual_sol, [0, 0, 0, 1])
342342

343343

test/optimization/test_exact_cover.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def bitfield(n, length):
4747
return [int(digit) for digit in result] # [2:] to chop off the "0b" part
4848

4949
subsets = len(self.list_of_subsets)
50-
maximum = 2**subsets
50+
maximum = 2 ** subsets
5151
for i in range(maximum):
5252
cur = bitfield(i, subsets)
5353
cur_v = exact_cover.check_solution_satisfiability(cur, self.list_of_subsets)

test/optimization/test_graph_partition.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def bitfield(n, length):
4343
return [int(digit) for digit in result] # [2:] to chop off the "0b" part
4444

4545
nodes = self.num_nodes
46-
maximum = 2**nodes
46+
maximum = 2 ** nodes
4747
minimal_v = np.inf
4848
for i in range(maximum):
4949
cur = bitfield(i, nodes)
@@ -64,7 +64,9 @@ def test_graph_partition(self):
6464
x = sample_most_likely(result.eigenstate)
6565
# check against the oracle
6666
ising_sol = graph_partition.get_graph_solution(x)
67-
np.testing.assert_array_equal(ising_sol, [0, 1, 0, 1])
67+
# solutions are equivalent
68+
self.assertEqual(graph_partition.objective_value(np.array([0, 1, 0, 1]), self.w),
69+
graph_partition.objective_value(ising_sol, self.w))
6870
oracle = self._brute_force()
6971
self.assertEqual(graph_partition.objective_value(x, self.w), oracle)
7072

@@ -82,7 +84,8 @@ def test_graph_partition_vqe(self):
8284
x = sample_most_likely(result['eigvecs'][0])
8385
# check against the oracle
8486
ising_sol = graph_partition.get_graph_solution(x)
85-
np.testing.assert_array_equal(ising_sol, [0, 1, 0, 1])
87+
self.assertEqual(graph_partition.objective_value(np.array([0, 1, 0, 1]), self.w),
88+
graph_partition.objective_value(ising_sol, self.w))
8689
oracle = self._brute_force()
8790
self.assertEqual(graph_partition.objective_value(x, self.w), oracle)
8891

test/optimization/test_partition.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ def test_partition(self):
4040
algo = NumPyMinimumEigensolver(self.qubit_op, aux_operators=[])
4141
result = algo.run()
4242
x = sample_most_likely(result.eigenstate)
43+
if x[0] != 0:
44+
x = np.logical_not(x) * 1
4345
np.testing.assert_array_equal(x, [0, 1, 0])
4446

4547
def test_partition_vqe(self):

test/optimization/test_qaoa.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
{'label': 'IIXI', 'coeff': {'real': 1}},
4040
{'label': 'IXII', 'coeff': {'real': 1}},
4141
{'label': 'XIII', 'coeff': {'real': 1}}]
42-
})
42+
}).to_opflow()
4343
S1 = {'0101', '1010'}
4444

4545

@@ -58,11 +58,13 @@
5858
class TestQAOA(QiskitOptimizationTestCase):
5959
"""Test QAOA with MaxCut."""
6060
@idata([
61-
[W1, P1, M1, S1],
62-
[W2, P2, M2, S2],
61+
[W1, P1, M1, S1, False],
62+
[W2, P2, M2, S2, False],
63+
[W1, P1, M1, S1, True],
64+
[W2, P2, M2, S2, True],
6365
])
6466
@unpack
65-
def test_qaoa(self, w, prob, m, solutions):
67+
def test_qaoa(self, w, prob, m, solutions, convert_to_matrix_op):
6668
""" QAOA test """
6769
seed = 0
6870
aqua_globals.random_seed = seed
@@ -71,6 +73,9 @@ def test_qaoa(self, w, prob, m, solutions):
7173
backend = BasicAer.get_backend('statevector_simulator')
7274
optimizer = COBYLA()
7375
qubit_op, offset = max_cut.get_operator(w)
76+
qubit_op = qubit_op.to_opflow()
77+
if convert_to_matrix_op:
78+
qubit_op = qubit_op.to_matrix_op()
7479

7580
qaoa = QAOA(qubit_op, optimizer, prob, mixer=m)
7681
quantum_instance = QuantumInstance(backend, seed_simulator=seed, seed_transpiler=seed)

test/optimization/test_set_packing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def bitfield(n, length):
4444
return [int(digit) for digit in result] # [2:] to chop off the "0b" part
4545

4646
subsets = len(self.list_of_subsets)
47-
maximum = 2**subsets
47+
maximum = 2 ** subsets
4848
max_v = -np.inf
4949
for i in range(maximum):
5050
cur = bitfield(i, subsets)

test/optimization/test_tsp.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ def test_tsp(self):
4040
algo = NumPyMinimumEigensolver(self.qubit_op)
4141
result = algo.run()
4242
x = sample_most_likely(result.eigenstate)
43+
# print(self.qubit_op.to_opflow().eval(result.eigenstate).adjoint().eval(result.eigenstate))
4344
order = tsp.get_tsp_solution(x)
44-
np.testing.assert_array_equal(order, [1, 2, 0])
45+
np.testing.assert_equal(tsp.tsp_value(order, self.ins.w),
46+
tsp.tsp_value([1, 2, 0], self.ins.w))
47+
48+
49+
if __name__ == '__main__':
50+
unittest.main()
4551

4652

4753
if __name__ == '__main__':

test/optimization/test_vehicle_routing.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ def test_simple2(self):
6464
# Solve the problem using the exact eigensolver
6565
result = NumPyMinimumEigensolver(self.qubit_op).run()
6666
arr = np.array([0., 0., 0., 1.])
67-
np.testing.assert_array_almost_equal(arr, result.eigenstate, 4)
67+
np.testing.assert_array_almost_equal(arr, np.abs(result.eigenstate.to_matrix()) ** 2, 4)
68+
69+
70+
if __name__ == '__main__':
71+
unittest.main()
6872

6973

7074
if __name__ == '__main__':

test/optimization/test_vertex_cover.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def bitfield(n, length):
4545
return [int(digit) for digit in result] # [2:] to chop off the "0b" part
4646

4747
nodes = self.num_nodes
48-
maximum = 2**nodes
48+
maximum = 2 ** nodes
4949
minimal_v = np.inf
5050
for i in range(maximum):
5151
cur = bitfield(i, nodes)

0 commit comments

Comments
 (0)