From 960c8d261868fd8cef2568f9bbdd34e248d33af7 Mon Sep 17 00:00:00 2001 From: Richard Chen Date: Mon, 5 Aug 2019 11:39:49 -0400 Subject: [PATCH 1/7] expose more apis and update the warning message --- qiskit/aqua/operators/__init__.py | 10 +++++++++- qiskit/aqua/operators/common.py | 4 ++-- qiskit/aqua/operators/op_converter.py | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/qiskit/aqua/operators/__init__.py b/qiskit/aqua/operators/__init__.py index 31a02d2dfa..bbac01004f 100644 --- a/qiskit/aqua/operators/__init__.py +++ b/qiskit/aqua/operators/__init__.py @@ -12,7 +12,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -from .common import evolution_instruction, suzuki_expansion_slice_pauli_list +from .common import (evolution_instruction, suzuki_expansion_slice_pauli_list, pauli_measurement, + measure_pauli_z, covariance, row_echelon_F2, kernel_F2, commutator, check_commutativity) from .pauli_graph import PauliGraph from .base_operator import BaseOperator from .weighted_pauli_operator import WeightedPauliOperator, Z2Symmetries @@ -22,6 +23,13 @@ __all__ = [ 'evolution_instruction', 'suzuki_expansion_slice_pauli_list', + 'pauli_measurement', + 'measure_pauli_z', + 'covariance', + 'row_echelon_F2', + 'kernel_F2', + 'commutator', + 'check_commutativity', 'PauliGraph', 'BaseOperator', 'WeightedPauliOperator', diff --git a/qiskit/aqua/operators/common.py b/qiskit/aqua/operators/common.py index 79bd4a320b..4888afbcfa 100644 --- a/qiskit/aqua/operators/common.py +++ b/qiskit/aqua/operators/common.py @@ -391,7 +391,7 @@ def commutator(op_a, op_b, op_c=None, threshold=None): tmp = 0.5 * tmp res = op_abc + op_cba - tmp - if threshold is not None: - res.chop(1e-12) + threshold = 1e-12 if threshold is None else threshold + res.chop(threshold) res.simplify() return res diff --git a/qiskit/aqua/operators/op_converter.py b/qiskit/aqua/operators/op_converter.py index 929648921f..2028dc2213 100644 --- a/qiskit/aqua/operators/op_converter.py +++ b/qiskit/aqua/operators/op_converter.py @@ -55,7 +55,8 @@ def to_weighted_pauli_operator(operator): elif operator.__class__ == MatrixOperator: if operator.is_empty(): return WeightedPauliOperator(paulis=[]) - logger.warning("Convert from a MatrixOperator to a Pauli-type Operator requires exponential time. " + logger.warning("Converting time from a MatrixOperator to a Pauli-type Operator grows exponentially. " + "If you are converting a system with large number of qubits, it will take time. " "You can turn on DEBUG logging to check the progress.") num_qubits = operator.num_qubits coeff = 2 ** (-num_qubits) From c08a1a95345025e3b7d7cef8f9151444d9111b20 Mon Sep 17 00:00:00 2001 From: Richard Chen Date: Tue, 6 Aug 2019 00:05:53 -0400 Subject: [PATCH 2/7] potential bug fix --- qiskit/aqua/operators/common.py | 8 +++++--- qiskit/aqua/operators/weighted_pauli_operator.py | 16 +++++++++++----- .../components/initial_states/hartree_fock.py | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/qiskit/aqua/operators/common.py b/qiskit/aqua/operators/common.py index 4888afbcfa..d2de058716 100644 --- a/qiskit/aqua/operators/common.py +++ b/qiskit/aqua/operators/common.py @@ -242,10 +242,12 @@ def evolution_instruction(pauli_list, evo_time, num_time_slices, state_registers = QuantumRegister(pauli_list[0][1].numberofqubits) if controlled: + inst_name = 'Controlled-Evolution^{}'.format(power) ancillary_registers = QuantumRegister(1) - qc_slice = QuantumCircuit(state_registers, ancillary_registers, name='Controlled-Evolution^{}'.format(power)) + qc_slice = QuantumCircuit(state_registers, ancillary_registers, name=inst_name) else: - qc_slice = QuantumCircuit(state_registers, name='Evolution^{}'.format(power)) + inst_name = 'Evolution^{}'.format(power) + qc_slice = QuantumCircuit(state_registers, name=inst_name) # for each pauli [IXYZ]+, record the list of qubit pairs needing CX's cnot_qubit_pairs = [None] * len(pauli_list) @@ -343,7 +345,7 @@ def evolution_instruction(pauli_list, evo_time, num_time_slices, qc_slice.data *= (num_time_slices * power) qc = qc_slice else: - qc = QuantumCircuit() + qc = QuantumCircuit(name=inst_name) for _ in range(num_time_slices * power): qc += qc_slice qc.barrier(state_registers) diff --git a/qiskit/aqua/operators/weighted_pauli_operator.py b/qiskit/aqua/operators/weighted_pauli_operator.py index c36ff6d8b5..1269aaeb3b 100644 --- a/qiskit/aqua/operators/weighted_pauli_operator.py +++ b/qiskit/aqua/operators/weighted_pauli_operator.py @@ -177,9 +177,9 @@ def _add_or_sub(self, other, operation, copy=True): if idx is not None: ret_op._paulis[idx][0] = operation(ret_op._paulis[idx][0], pauli[0]) else: - ret_op._paulis_table[pauli_label] = len(ret_op._paulis) - ret_op._basis.append((pauli[1], [len(ret_op._paulis)])) new_pauli = deepcopy(pauli) + ret_op._paulis_table[pauli_label] = len(ret_op._paulis) + ret_op._basis.append((new_pauli[1], [len(ret_op._paulis)])) new_pauli[0] = operation(0.0, pauli[0]) ret_op._paulis.append(new_pauli) return ret_op @@ -339,9 +339,15 @@ def simplify(self, copy=False): new_paulis_table[pauli_label] = len(new_paulis) new_paulis.append([curr_weight, curr_pauli]) - op._paulis = new_paulis - op._paulis_table = {weighted_pauli[1].to_label(): i for i, weighted_pauli in enumerate(new_paulis)} - op.chop(0.0) + new_paulis_2 = [] + for weight, pauli in new_paulis: + if weight == 0.0: + continue + new_paulis_2.append([weight, pauli]) + + op._paulis = new_paulis_2 + op._paulis_table = {weighted_pauli[1].to_label(): i for i, weighted_pauli in enumerate(op._paulis)} + op._basis = [(pauli[1], [i]) for i, pauli in enumerate(op._paulis)] return op def rounding(self, decimals, copy=False): diff --git a/qiskit/chemistry/aqua_extensions/components/initial_states/hartree_fock.py b/qiskit/chemistry/aqua_extensions/components/initial_states/hartree_fock.py index 3b35b61335..621b4dac5b 100644 --- a/qiskit/chemistry/aqua_extensions/components/initial_states/hartree_fock.py +++ b/qiskit/chemistry/aqua_extensions/components/initial_states/hartree_fock.py @@ -82,7 +82,7 @@ def __init__(self, num_qubits, num_orbitals, num_particles, self.validate(locals()) super().__init__() self._sq_list = sq_list - self._qubit_tapering = False if self._sq_list is None else True + self._qubit_tapering = False if self._sq_list is None or self._sq_list == [] else True self._qubit_mapping = qubit_mapping.lower() self._two_qubit_reduction = two_qubit_reduction if self._qubit_mapping != 'parity': From 504e7b370ae23b7e8a1486d1da47392c8c73d1b4 Mon Sep 17 00:00:00 2001 From: Richard Chen Date: Tue, 6 Aug 2019 10:19:15 -0400 Subject: [PATCH 3/7] bug fix and support simplfy for grouped paulis --- .../aqua/operators/weighted_pauli_operator.py | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/qiskit/aqua/operators/weighted_pauli_operator.py b/qiskit/aqua/operators/weighted_pauli_operator.py index 1269aaeb3b..746d82b6c0 100644 --- a/qiskit/aqua/operators/weighted_pauli_operator.py +++ b/qiskit/aqua/operators/weighted_pauli_operator.py @@ -330,24 +330,36 @@ def simplify(self, copy=False): new_paulis = [] new_paulis_table = {} + old_to_new_indices = {} + curr_idx = 0 for curr_weight, curr_pauli in op.paulis: pauli_label = curr_pauli.to_label() new_idx = new_paulis_table.get(pauli_label, None) if new_idx is not None: new_paulis[new_idx][0] += curr_weight + old_to_new_indices[curr_idx] = new_idx else: new_paulis_table[pauli_label] = len(new_paulis) + old_to_new_indices[curr_idx] = len(new_paulis) new_paulis.append([curr_weight, curr_pauli]) + curr_idx += 1 - new_paulis_2 = [] - for weight, pauli in new_paulis: - if weight == 0.0: - continue - new_paulis_2.append([weight, pauli]) - - op._paulis = new_paulis_2 - op._paulis_table = {weighted_pauli[1].to_label(): i for i, weighted_pauli in enumerate(op._paulis)} - op._basis = [(pauli[1], [i]) for i, pauli in enumerate(op._paulis)] + op._paulis = new_paulis + op._paulis_table = new_paulis_table + # update the grouping info, since this method only remove pauli, we can handle it here for both + # pauli and tpb grouped pauli + new_basis = [] + for basis, indices in op.basis: + new_indices = [] + for idx in indices: + new_idx = old_to_new_indices[idx] + if new_idx is not None: + new_indices.append(new_idx) + new_indices = list(set(new_indices)) + if len(new_indices) > 0: + new_basis.append((basis, new_indices)) + op._basis = new_basis + op.chop(0.0) return op def rounding(self, decimals, copy=False): From 2db1dbd85e79a229618ae1b474d1c73f809d7f9d Mon Sep 17 00:00:00 2001 From: Richard Chen Date: Tue, 6 Aug 2019 10:35:36 -0400 Subject: [PATCH 4/7] bug fix --- qiskit/aqua/operators/weighted_pauli_operator.py | 13 +++++++++++-- test/aqua/operators/test_weighted_pauli_operator.py | 13 +++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/qiskit/aqua/operators/weighted_pauli_operator.py b/qiskit/aqua/operators/weighted_pauli_operator.py index 746d82b6c0..8f9b146e71 100644 --- a/qiskit/aqua/operators/weighted_pauli_operator.py +++ b/qiskit/aqua/operators/weighted_pauli_operator.py @@ -346,17 +346,26 @@ def simplify(self, copy=False): op._paulis = new_paulis op._paulis_table = new_paulis_table - # update the grouping info, since this method only remove pauli, we can handle it here for both + + # update the grouping info, since this method only reduce the number of paulis, we can handle it here for both # pauli and tpb grouped pauli + # should have a better way to rebuild the basis here. new_basis = [] for basis, indices in op.basis: new_indices = [] + found = False + if len(new_basis) > 0: + for b, ind in new_basis: + if b == basis: + new_indices = ind + found = True + break for idx in indices: new_idx = old_to_new_indices[idx] if new_idx is not None: new_indices.append(new_idx) new_indices = list(set(new_indices)) - if len(new_indices) > 0: + if len(new_indices) > 0 and not found: new_basis.append((basis, new_indices)) op._basis = new_basis op.chop(0.0) diff --git a/test/aqua/operators/test_weighted_pauli_operator.py b/test/aqua/operators/test_weighted_pauli_operator.py index 6150fded80..0e32e267fb 100644 --- a/test/aqua/operators/test_weighted_pauli_operator.py +++ b/test/aqua/operators/test_weighted_pauli_operator.py @@ -271,6 +271,19 @@ def test_simplify(self): op1.simplify() self.assertEqual(len(paulis) - (i + 1), len(op1.paulis)) + def test_simplify_same_paulis(self): + pauli_a = 'IXYZ' + pauli_b = 'IXYZ' + coeff_a = 0.5 + coeff_b = 0.5 + pauli_term_a = [coeff_a, Pauli.from_label(pauli_a)] + pauli_term_b = [coeff_b, Pauli.from_label(pauli_b)] + op_a = WeightedPauliOperator(paulis=[pauli_term_a, pauli_term_b]) + + self.assertEqual(1, len(op_a.paulis), "{}".format(op_a.print_details())) + self.assertEqual(1, len(op_a.basis)) + self.assertEqual(0, op_a.basis[0][1][0]) + def test_chop_real(self): paulis = [Pauli.from_label(x) for x in ['IXYZ', 'XXZY', 'IIZZ', 'XXYY', 'ZZXX', 'YYYY']] From aacc196945b57af80427a57e257aebe382c3abc9 Mon Sep 17 00:00:00 2001 From: Richard Chen Date: Tue, 6 Aug 2019 11:24:44 -0400 Subject: [PATCH 5/7] change default to 1e-12 --- qiskit/aqua/operators/common.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/qiskit/aqua/operators/common.py b/qiskit/aqua/operators/common.py index d2de058716..41c1fd97e5 100644 --- a/qiskit/aqua/operators/common.py +++ b/qiskit/aqua/operators/common.py @@ -352,7 +352,7 @@ def evolution_instruction(pauli_list, evo_time, num_time_slices, return qc.to_instruction() -def commutator(op_a, op_b, op_c=None, threshold=None): +def commutator(op_a, op_b, op_c=None, threshold=1e-12): """ Compute commutator of op_a and op_b or the symmetric double commutator of op_a, op_b and op_c. @@ -393,7 +393,6 @@ def commutator(op_a, op_b, op_c=None, threshold=None): tmp = 0.5 * tmp res = op_abc + op_cba - tmp - threshold = 1e-12 if threshold is None else threshold - res.chop(threshold) res.simplify() + res.chop(threshold) return res From 7ca391318cfb7f918c36ad866a4f668bbbbee7c9 Mon Sep 17 00:00:00 2001 From: Richard Chen Date: Tue, 6 Aug 2019 16:12:11 -0400 Subject: [PATCH 6/7] update test and info level --- qiskit/aqua/algorithms/adaptive/vqe/vqe.py | 6 +++--- .../operators/test_tpb_grouped_weigted_pauli_operator.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/qiskit/aqua/algorithms/adaptive/vqe/vqe.py b/qiskit/aqua/algorithms/adaptive/vqe/vqe.py index 789702d130..95c593ee23 100644 --- a/qiskit/aqua/algorithms/adaptive/vqe/vqe.py +++ b/qiskit/aqua/algorithms/adaptive/vqe/vqe.py @@ -202,14 +202,14 @@ def print_settings(self): def _config_the_best_mode(self, operator, backend): if not isinstance(operator, (WeightedPauliOperator, MatrixOperator, TPBGroupedWeightedPauliOperator)): - logger.info("Unrecognized operator type, skip auto conversion.") + logger.debug("Unrecognized operator type, skip auto conversion.") return operator ret_op = operator if not is_statevector_backend(backend): # assume qasm, should use grouped paulis. if isinstance(operator, (WeightedPauliOperator, MatrixOperator)): - logger.info("When running with Qasm simulator, grouped pauli can save number of measurements. " - "We convert the operator into grouped ones.") + logger.debug("When running with Qasm simulator, grouped pauli can save number of measurements. " + "We convert the operator into grouped ones.") ret_op = op_converter.to_tpb_grouped_weighted_pauli_operator( operator, TPBGroupedWeightedPauliOperator.sorted_grouping) else: diff --git a/test/aqua/operators/test_tpb_grouped_weigted_pauli_operator.py b/test/aqua/operators/test_tpb_grouped_weigted_pauli_operator.py index b57c7cde03..d7ee85b25f 100644 --- a/test/aqua/operators/test_tpb_grouped_weigted_pauli_operator.py +++ b/test/aqua/operators/test_tpb_grouped_weigted_pauli_operator.py @@ -141,7 +141,8 @@ def test_equal(self): TPBGroupedWeightedPauliOperator.sorted_grouping) gop_2 = op_converter.to_tpb_grouped_weighted_pauli_operator(self.qubit_op, TPBGroupedWeightedPauliOperator.unsorted_grouping) - self.assertNotEqual(gop_1, gop_2) + + self.assertEqual(gop_1, gop_2) if __name__ == '__main__': From a052c5d845ce2aa806fe656c3f7ccc7a55864b09 Mon Sep 17 00:00:00 2001 From: Richard Chen Date: Wed, 7 Aug 2019 15:49:20 -0400 Subject: [PATCH 7/7] use assemble rather than assemble circuits and do not convert the type of coupling map at aqua, terra should handle that --- qiskit/aqua/quantum_instance.py | 3 --- qiskit/aqua/utils/run_circuits.py | 7 ++----- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/qiskit/aqua/quantum_instance.py b/qiskit/aqua/quantum_instance.py index 9ff6e33544..808ccf24d4 100644 --- a/qiskit/aqua/quantum_instance.py +++ b/qiskit/aqua/quantum_instance.py @@ -19,7 +19,6 @@ from qiskit import __version__ as terra_version from qiskit.assembler.run_config import RunConfig -from qiskit.transpiler import CouplingMap from .aqua_error import AquaError from .utils import (run_qobj, compile_circuits, CircuitCache, @@ -126,8 +125,6 @@ def __init__(self, backend, # setup backend config basis_gates = basis_gates or backend.configuration().basis_gates coupling_map = coupling_map or getattr(backend.configuration(), 'coupling_map', None) - if coupling_map is not None and not isinstance(coupling_map, CouplingMap): - coupling_map = CouplingMap(coupling_map) self._backend_config = { 'basis_gates': basis_gates, 'coupling_map': coupling_map diff --git a/qiskit/aqua/utils/run_circuits.py b/qiskit/aqua/utils/run_circuits.py index 589c02eb44..007f40438e 100644 --- a/qiskit/aqua/utils/run_circuits.py +++ b/qiskit/aqua/utils/run_circuits.py @@ -21,11 +21,10 @@ import numpy as np from qiskit import compiler -from qiskit.assembler import assemble_circuits from qiskit.providers import BaseBackend, JobStatus, JobError from qiskit.providers.jobstatus import JOB_FINAL_STATES from qiskit.providers.basicaer import BasicAerJob -from qiskit.qobj import QobjHeader, QasmQobj +from qiskit.qobj import QasmQobj from qiskit.aqua.aqua_error import AquaError from qiskit.aqua.utils import summarize_circuits from qiskit.aqua.utils.backend_utils import (is_aer_provider, @@ -120,9 +119,7 @@ def _compile_wrapper(circuits, backend, backend_config, compile_config, run_conf transpiled_circuits = compiler.transpile(circuits, backend, **backend_config, **compile_config) if not isinstance(transpiled_circuits, list): transpiled_circuits = [transpiled_circuits] - - qobj = assemble_circuits(transpiled_circuits, qobj_id=str(uuid.uuid4()), qobj_header=QobjHeader(), - run_config=run_config) + qobj = compiler.assemble(transpiled_circuits, **run_config.to_dict()) return qobj, transpiled_circuits