From 06b25de65c8df85ae4da2e35a8e0f6a51e3717e3 Mon Sep 17 00:00:00 2001 From: Donny Greenberg Date: Thu, 2 Apr 2020 08:52:32 -0400 Subject: [PATCH] Add Parameterized Qobj tests. --- .../terra/backends/test_parameterized_qobj.py | 127 ++++++++++++++++++ test/terra/reference/ref_snapshot_expval.py | 113 +++++++++++++++- 2 files changed, 235 insertions(+), 5 deletions(-) create mode 100644 test/terra/backends/test_parameterized_qobj.py diff --git a/test/terra/backends/test_parameterized_qobj.py b/test/terra/backends/test_parameterized_qobj.py new file mode 100644 index 0000000000..f56d9ebc0f --- /dev/null +++ b/test/terra/backends/test_parameterized_qobj.py @@ -0,0 +1,127 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2018, 2019. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +""" +Integration Tests for Parameterized Qobj execution, testing qasm_simulator, +statevector_simulator, and expectation value snapshots. +""" + +import unittest +import numpy as np + +from test.terra import common + +from qiskit import assemble +from test.terra.reference.ref_snapshot_expval import ( + snapshot_expval_circuits, snapshot_expval_counts, snapshot_expval_labels, + snapshot_expval_pre_meas_values, snapshot_expval_circuit_parameterized, + snapshot_expval_final_statevecs) +from qiskit.providers.aer import QasmSimulator, StatevectorSimulator + + +class TestParameterizedQobj(common.QiskitAerTestCase): + """Parameterized Qobj extension tests""" + + BACKEND_OPTS = { + "seed_simulator": 2113 + } + + @staticmethod + def expval_snapshots(data, labels): + """Format snapshots as nested dicts""" + # Check snapshot entry exists in data + output = {} + for label in labels: + snaps = data.get("snapshots", {}).get("expectation_value", + {}).get(label, []) + # Convert list into dict + inner = {} + for snap_dict in snaps: + inner[snap_dict['memory']] = snap_dict['value'] + output[label] = inner + return output + + @staticmethod + def parameterized_qobj(backend, shots=1000, measure=True, snapshot=False): + """Return ParameterizedQobj for settings.""" + single_shot = shots == 1 + pcirc1, param1 = snapshot_expval_circuit_parameterized(single_shot=single_shot, + measure=measure, + snapshot=snapshot) + circuits2to4 = snapshot_expval_circuits(pauli=True, + skip_measure=(not measure), + single_shot=single_shot) + pcirc2, param2 = snapshot_expval_circuit_parameterized(single_shot=single_shot, + measure=measure, + snapshot=snapshot) + circuits = [pcirc1] + circuits2to4 + [pcirc2] + params = [param1, [], [], [], param2] + qobj = assemble(circuits, + backend=backend, + shots=shots, + parameterizations=params) + return qobj + + def test_parameterized_qobj_qasm_snapshot_expval(self): + """Test parameterized qobj with Expectation Value snapshot and qasm simulator.""" + shots = 1000 + labels = snapshot_expval_labels() * 3 + counts_targets = snapshot_expval_counts(shots) * 3 + value_targets = snapshot_expval_pre_meas_values() * 3 + + backend = QasmSimulator() + qobj = self.parameterized_qobj(backend=backend, + shots=1000, + measure=True, + snapshot=True) + self.assertIn('parameterizations', qobj.to_dict()['config']) + job = backend.run(qobj, self.BACKEND_OPTS) + result = job.result() + success = getattr(result, 'success', False) + num_circs = len(result.to_dict()['results']) + self.assertTrue(success) + self.compare_counts(result, + range(num_circs), + counts_targets, + delta=0.1 * shots) + # Check snapshots + for j in range(num_circs): + data = result.data(j) + all_snapshots = self.expval_snapshots(data, labels) + for label in labels: + snaps = all_snapshots.get(label, {}) + self.assertTrue(len(snaps), 1) + for memory, value in snaps.items(): + target = value_targets[j].get(label, + {}).get(memory, {}) + self.assertAlmostEqual(value, target, delta=1e-7) + + def test_parameterized_qobj_statevector(self): + """Test parameterized qobj with Expectation Value snapshot and qasm simulator.""" + statevec_targets = snapshot_expval_final_statevecs() * 3 + + backend = StatevectorSimulator() + qobj = self.parameterized_qobj(backend=backend, + measure=False, + snapshot=False) + self.assertIn('parameterizations', qobj.to_dict()['config']) + job = backend.run(qobj, self.BACKEND_OPTS) + result = job.result() + success = getattr(result, 'success', False) + num_circs = len(result.to_dict()['results']) + self.assertTrue(success) + + for j in range(num_circs): + statevector = result.get_statevector(j) + np.testing.assert_array_almost_equal(statevector, statevec_targets[j].data, decimal=7) + +if __name__ == '__main__': + unittest.main() diff --git a/test/terra/reference/ref_snapshot_expval.py b/test/terra/reference/ref_snapshot_expval.py index abe4ddb1c1..7e6200a070 100644 --- a/test/terra/reference/ref_snapshot_expval.py +++ b/test/terra/reference/ref_snapshot_expval.py @@ -69,7 +69,8 @@ def snapshot_expval_params(pauli=False): def snapshot_expval_circuits(pauli=False, single_shot=False, variance=False, - post_measure=False): + post_measure=False, + skip_measure=False): """SnapshotExpectationValue test circuits with deterministic counts""" circuits = [] @@ -91,7 +92,8 @@ def snapshot_expval_circuits(pauli=False, single_shot=single_shot, variance=variance) circuit.barrier(qr) - circuit.measure(qr, cr) + if not skip_measure: + circuit.measure(qr, cr) circuit.barrier(qr) if post_measure: for label, (params, @@ -116,7 +118,8 @@ def snapshot_expval_circuits(pauli=False, single_shot=single_shot, variance=variance) circuit.barrier(qr) - circuit.measure(qr, cr) + if not skip_measure: + circuit.measure(qr, cr) circuit.barrier(qr) if post_measure: for label, (params, @@ -131,7 +134,7 @@ def snapshot_expval_circuits(pauli=False, # State |10> -i|01> circuit = QuantumCircuit(*regs) circuit.h(0) - circuit.s(0) + circuit.sdg(0) circuit.cx(0, 1) circuit.x(1) if not post_measure: @@ -143,7 +146,8 @@ def snapshot_expval_circuits(pauli=False, single_shot=single_shot, variance=variance) circuit.barrier(qr) - circuit.measure(qr, cr) + if not skip_measure: + circuit.measure(qr, cr) circuit.barrier(qr) if post_measure: for label, (params, @@ -218,3 +222,102 @@ def snapshot_expval_post_meas_values(): values[label] = inner_dict targets.append(values) return targets + +def snapshot_expval_circuit_parameterized(single_shot=False, + measure=True, + snapshot=False): + """SnapshotExpectationValue test circuits, rewritten as a single parameterized circuit and + parameterizations array. """ + + num_qubits = 2 + qr = QuantumRegister(num_qubits) + cr = ClassicalRegister(num_qubits) + regs = (qr, cr) + + circuit = QuantumCircuit(*regs) + circuit.u3(0, 0, 0, qubit=0) + circuit.u1(0, qubit=0) + circuit.u3(0, 0, 0, qubit=1) + circuit.cu3(0, 0, 0, control_qubit=0, target_qubit=1) + circuit.u3(0, 0, 0, qubit=1) + circuit.id(qubit=0) + if snapshot: + for label, (params, qubits) in snapshot_expval_params(pauli=True).items(): + circuit.snapshot_expectation_value(label, + params, + qubits, + single_shot=single_shot) + if measure: + circuit.barrier(qr) + circuit.measure(qr, cr) + circuit.barrier(qr) + + # Parameterizations + + # State |+1> + plus_one_params = { + # X on 0 + (0, 0): np.pi, + (0, 1): 0, + (0, 2): np.pi, + # No rZ + (1, 0): 0, + # H on 1 + (2, 0): np.pi / 2, + (2, 2): np.pi, + # No CrX + (3, 0): 0, + (3, 1): 0, + (3, 2): 0, + # No X + (4, 0): 0, + (4, 1): 0, + (4, 2): 0, + } + # State |00> + |11> + bell_params = { + # H 0 + (0, 0): np.pi / 2, + (0, 1): 0, + (0, 2): np.pi, + # No rZ + (1, 0): 0, + # No H + (2, 0): 0, + (2, 2): 0, + # CX from 0 on 1 + (3, 0): np.pi, + (3, 1): 0, + (3, 2): np.pi, + # No X + (4, 0): 0, + (4, 1): 0, + (4, 2): 0, + } + # State |10> -i|01> + iminus_bell_params = { + # H 0 + (0, 0): np.pi / 2, + (0, 1): 0, + (0, 2): np.pi, + # S 0 + (1, 0): - np.pi / 2, + # No H + (2, 0): 0, + (2, 2): 0, + # CX from 0 on 1 + (3, 0): np.pi, + (3, 1): 0, + (3, 2): np.pi, + # X 1 + (4, 0): np.pi, + (4, 1): 0, + (4, 2): np.pi, + } + param_mat = np.transpose([list(plus_one_params.values()), + list(bell_params.values()), + list(iminus_bell_params.values())]).tolist() + parameterizations = [[list(index), params] + for (index, params) in zip(plus_one_params.keys(), param_mat)] + + return circuit, parameterizations