Skip to content

Commit

Permalink
Add snapshot probabilities tests
Browse files Browse the repository at this point in the history
  • Loading branch information
chriseclectic committed Oct 2, 2019
1 parent a727465 commit 711c215
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 4 deletions.
91 changes: 87 additions & 4 deletions test/terra/backends/qasm_simulator/qasm_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@
snapshot_state_counts_nondeterministic,
snapshot_state_pre_measure_statevector_nondeterministic,
snapshot_state_post_measure_statevector_nondeterministic)

def get_snapshots(data, label, snapshot_type):
"""Format snapshots as list of Numpy arrays"""
return data.get("snapshots", {}).get(snapshot_type, {}).get(label, [])
from test.terra.reference.ref_snapshot_probabilities import (
snapshot_probabilities_circuits,
snapshot_probabilities_counts,
snapshot_probabilities_labels_qubits,
snapshot_probabilities_post_meas_probs,
snapshot_probabilities_pre_meas_probs)


class QasmSnapshotStatevectorTests:
Expand Down Expand Up @@ -484,3 +486,84 @@ def test_snapshot_density_matrix_post_measure_nondet(self):
target = np.outer(target, target.conj())
value = snaps.get(mem)
self.assertTrue(np.allclose(value, target))


class QasmSnapshotProbabilitiesTests:
"""QasmSimulator snapshot probabilities tests."""

SIMULATOR = QasmSimulator()
SUPPORTED_QASM_METHODS = [
'automatic', 'statevector', 'density_matrix', 'matrix_product_state'
]
BACKEND_OPTS = {}

@staticmethod
def probabilitiy_snapshots(data, labels):
"""Format snapshots as nested dicts"""
# Check snapshot entry exists in data
output = {}
for label in labels:
snaps = data.get("snapshots", {}).get("probabilities", {}).get(label, [])
# Convert list into dict
inner = {}
for snap_dict in snaps:
inner[snap_dict['memory']] = snap_dict['value']
output[label] = inner
return output

def test_snapshot_probabilities_pre_measure(self):
"""Test snapshot probabilities before final measurement"""
shots = 1000
labels = list(snapshot_probabilities_labels_qubits().keys())
counts_targets = snapshot_probabilities_counts(shots)
prob_targets = snapshot_probabilities_pre_meas_probs()

circuits = snapshot_probabilities_circuits(post_measure=False)

qobj = assemble(circuits, self.SIMULATOR, shots=shots)
job = self.SIMULATOR.run(qobj, backend_options=self.BACKEND_OPTS)
method = self.BACKEND_OPTS.get('method', 'automatic')
if method not in QasmSnapshotProbabilitiesTests.SUPPORTED_QASM_METHODS:
self.assertRaises(AerError, job.result)
else:
result = job.result()
self.is_completed(result)
self.compare_counts(result, circuits, counts_targets, delta=0.1 * shots)
# Check snapshots
for j, circuit in enumerate(circuits):
data = result.data(circuit)
all_snapshots = self.probabilitiy_snapshots(data, labels)
for label in labels:
snaps = all_snapshots.get(label, {})
self.assertTrue(len(snaps), 1)
for memory, value in snaps.items():
target = prob_targets[j].get(label, {}).get(memory, {})
self.assertDictAlmostEqual(value, target, delta=1e-7)

def test_snapshot_probabilities_post_measure(self):
"""Test snapshot probabilities after final measurement"""
shots = 1000
labels = list(snapshot_probabilities_labels_qubits().keys())
counts_targets = snapshot_probabilities_counts(shots)
prob_targets = snapshot_probabilities_post_meas_probs()

circuits = snapshot_probabilities_circuits(post_measure=True)

qobj = assemble(circuits, self.SIMULATOR, shots=shots)
job = self.SIMULATOR.run(qobj, backend_options=self.BACKEND_OPTS)
method = self.BACKEND_OPTS.get('method', 'automatic')
if method not in QasmSnapshotProbabilitiesTests.SUPPORTED_QASM_METHODS:
self.assertRaises(AerError, job.result)
else:
result = job.result()
self.is_completed(result)
self.compare_counts(result, circuits, counts_targets, delta=0.1 * shots)
# Check snapshots
for j, circuit in enumerate(circuits):
data = result.data(circuit)
all_snapshots = self.probabilitiy_snapshots(data, labels)
for label in labels:
snaps = all_snapshots.get(label, {})
for memory, value in snaps.items():
target = prob_targets[j].get(label, {}).get(memory, {})
self.assertDictAlmostEqual(value, target, delta=1e-7)
2 changes: 2 additions & 0 deletions test/terra/backends/test_qasm_density_matrix_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotStatevectorTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotDensityMatrixTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotStabilizerTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotProbabilitiesTests


class TestQasmDensityMatrixSimulator(common.QiskitAerTestCase,
Expand Down Expand Up @@ -75,6 +76,7 @@ class TestQasmDensityMatrixSimulator(common.QiskitAerTestCase,
QasmKrausNoiseTests,
QasmSnapshotStatevectorTests,
QasmSnapshotDensityMatrixTests,
QasmSnapshotProbabilitiesTests,
QasmSnapshotStabilizerTests):
"""QasmSimulator density_matrix method tests."""

Expand Down
2 changes: 2 additions & 0 deletions test/terra/backends/test_qasm_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotStatevectorTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotDensityMatrixTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotStabilizerTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotProbabilitiesTests
# Other tests
from test.terra.backends.qasm_simulator.qasm_method import QasmMethodTests
from test.terra.backends.qasm_simulator.qasm_thread_management import QasmThreadManagementTests
Expand Down Expand Up @@ -85,6 +86,7 @@ class TestQasmSimulator(common.QiskitAerTestCase,
QasmBasicsTests,
QasmSnapshotStatevectorTests,
QasmSnapshotDensityMatrixTests,
QasmSnapshotProbabilitiesTests,
QasmSnapshotStabilizerTests):
"""QasmSimulator automatic method tests."""

Expand Down
2 changes: 2 additions & 0 deletions test/terra/backends/test_qasm_stabilizer_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotStatevectorTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotDensityMatrixTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotStabilizerTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotProbabilitiesTests
# Other tests
from test.terra.backends.qasm_simulator.qasm_method import QasmMethodTests

Expand All @@ -51,6 +52,7 @@ class TestQasmStabilizerSimulator(common.QiskitAerTestCase,
QasmPauliNoiseTests,
QasmSnapshotStatevectorTests,
QasmSnapshotDensityMatrixTests,
QasmSnapshotProbabilitiesTests,
QasmSnapshotStabilizerTests):
"""QasmSimulator stabilizer method tests."""

Expand Down
2 changes: 2 additions & 0 deletions test/terra/backends/test_qasm_statevector_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotStatevectorTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotDensityMatrixTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotStabilizerTests
from test.terra.backends.qasm_simulator.qasm_snapshot import QasmSnapshotProbabilitiesTests
# Other tests
from test.terra.backends.qasm_simulator.qasm_method import QasmMethodTests

Expand Down Expand Up @@ -75,6 +76,7 @@ class TestQasmStatevectorSimulator(common.QiskitAerTestCase,
QasmKrausNoiseTests,
QasmSnapshotStatevectorTests,
QasmSnapshotDensityMatrixTests,
QasmSnapshotProbabilitiesTests,
QasmSnapshotStabilizerTests):
"""QasmSimulator statevector method tests."""

Expand Down
173 changes: 173 additions & 0 deletions test/terra/reference/ref_snapshot_probabilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# 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.

"""
Test circuits and reference outputs for snapshot state instructions.
"""

from numpy import array
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.providers.aer.extensions.snapshot_probabilities import *


def snapshot_probabilities_labels_qubits():
"""Dictionary of labels and qubits for 3-qubit probability snapshots"""
return {
"[0]": [0],
"[1]": [1],
"[2]": [2],
"[0, 1]": [0, 1],
"[1, 0]": [1, 0],
"[0, 2]": [0, 2],
"[2, 0]": [2, 0],
"[1, 2]": [1, 2],
"[2, 1]": [2, 1],
"[0, 1, 2]": [0, 1, 2],
"[1, 2, 0]": [1, 2, 0],
"[2, 0, 1]": [2, 0, 1]
}


def snapshot_probabilities_circuits(post_measure=False):
"""Snapshot Probabilities test circuits with deterministic counts"""

circuits = []
num_qubits = 3
qr = QuantumRegister(num_qubits)
cr = ClassicalRegister(num_qubits)
regs = (qr, cr)

# State |01+>
circuit = QuantumCircuit(*regs)
circuit.h(0)
circuit.x(1)
if not post_measure:
for label, qubits in snapshot_probabilities_labels_qubits().items():
circuit.snapshot_probabilities(label, qubits)
circuit.barrier(qr)
circuit.measure(qr, cr)
circuit.barrier(qr)
if post_measure:
for label, qubits in snapshot_probabilities_labels_qubits().items():
circuit.snapshot_probabilities(label, qubits)
circuits.append(circuit)

# State |010> -i|101>
circuit = QuantumCircuit(*regs)
circuit.h(0)
circuit.sdg(0)
circuit.cx(0, 1)
circuit.cx(0, 2)
circuit.x(1)
if not post_measure:
for label, qubits in snapshot_probabilities_labels_qubits().items():
circuit.snapshot_probabilities(label, qubits)
circuit.barrier(qr)
circuit.measure(qr, cr)
circuit.barrier(qr)
if post_measure:
for label, qubits in snapshot_probabilities_labels_qubits().items():
circuit.snapshot_probabilities(label, qubits)
circuits.append(circuit)

return circuits


def snapshot_probabilities_counts(shots):
"""Snapshot Probabilities test circuits reference counts."""
targets = []
# State |01+>
targets.append({'0x2': shots / 2, '0x3': shots / 2})

# State |010> -i|101>
targets.append({'0x2': shots / 2, '0x5': shots / 2})
return targets


def snapshot_probabilities_pre_meas_probs():
"""Snapshot Probabilities test circuits reference final probs"""
targets = []

# State |01+>
probs = {
"[0]": {'0x0': {'0x0': 0.5, '0x1': 0.5}},
"[1]": {'0x0': {'0x1': 1.0}},
"[2]": {'0x0': {'0x0': 1.0}},
"[0, 1]": {'0x0': {'0x2': 0.5, '0x3': 0.5}},
"[1, 0]": {'0x0': {'0x1': 0.5, '0x3': 0.5}},
"[0, 2]": {'0x0': {'0x0': 0.5, '0x1': 0.5}},
"[2, 0]": {'0x0': {'0x0': 0.5, '0x2': 0.5}},
"[1, 2]": {'0x0': {'0x1': 1.0}},
"[2, 1]": {'0x0': {'0x2': 1.0}},
"[0, 1, 2]": {'0x0': {'0x2': 0.5, '0x3': 0.5}},
"[1, 2, 0]": {'0x0': {'0x1': 0.5, '0x5': 0.5}},
"[2, 0, 1]": {'0x0': {'0x4': 0.5, '0x6': 0.5}},
}
targets.append(probs)

# State |010> -i|101>
probs = {
"[0]": {'0x0': {'0x0': 0.5, '0x1': 0.5}},
"[1]": {'0x0': {'0x0': 0.5, '0x1': 0.5}},
"[2]": {'0x0': {'0x0': 0.5, '0x1': 0.5}},
"[0, 1]": {'0x0': {'0x1': 0.5, '0x2': 0.5}},
"[1, 0]": {'0x0': {'0x1': 0.5, '0x2': 0.5}},
"[0, 2]": {'0x0': {'0x0': 0.5, '0x3': 0.5}},
"[2, 0]": {'0x0': {'0x0': 0.5, '0x3': 0.5}},
"[1, 2]": {'0x0': {'0x1': 0.5, '0x2': 0.5}},
"[2, 1]": {'0x0': {'0x1': 0.5, '0x2': 0.5}},
"[0, 1, 2]": {'0x0': {'0x2': 0.5, '0x5': 0.5}},
"[1, 2, 0]": {'0x0': {'0x1': 0.5, '0x6': 0.5}},
"[2, 0, 1]": {'0x0': {'0x3': 0.5, '0x4': 0.5}},
}
targets.append(probs)
return targets


def snapshot_probabilities_post_meas_probs():
"""Snapshot Probabilities test circuits reference final statevector"""
targets = []

# State |01+>
probs = {
"[0]": {'0x2': {'0x0': 1.0}, '0x3': {'0x1': 1.0}},
"[1]": {'0x2': {'0x1': 1.0}, '0x3': {'0x1': 1.0}},
"[2]": {'0x2': {'0x0': 1.0}, '0x3': {'0x0': 1.0}},
"[0, 1]": {'0x2': {'0x2': 1.0}, '0x3': {'0x3': 1.0}},
"[1, 0]": {'0x2': {'0x1': 1.0}, '0x3': {'0x3': 1.0}},
"[0, 2]": {'0x2': {'0x0': 1.0}, '0x3': {'0x1': 1.0}},
"[2, 0]": {'0x2': {'0x0': 1.0}, '0x3': {'0x2': 1.0}},
"[1, 2]": {'0x2': {'0x1': 1.0}, '0x3': {'0x1': 1.0}},
"[2, 1]": {'0x2': {'0x2': 1.0}, '0x3': {'0x2': 1.0}},
"[0, 1, 2]": {'0x2': {'0x2': 1.0}, '0x3': {'0x3': 1.0}},
"[1, 2, 0]": {'0x2': {'0x1': 1.0}, '0x3': {'0x5': 1.0}},
"[2, 0, 1]": {'0x2': {'0x4': 1.0}, '0x3': {'0x6': 1.0}},
}
targets.append(probs)

# State |010> -i|101>
probs = {
"[0]": {'0x2': {'0x0': 1.0}, '0x5': {'0x1': 1.0}},
"[1]": {'0x2': {'0x1': 1.0}, '0x5': {'0x0': 1.0}},
"[2]": {'0x2': {'0x0': 1.0}, '0x5': {'0x1': 1.0}},
"[0, 1]": {'0x2': {'0x2': 1.0}, '0x5': {'0x1': 1.0}},
"[1, 0]": {'0x2': {'0x1': 1.0}, '0x5': {'0x2': 1.0}},
"[0, 2]": {'0x2': {'0x0': 1.0}, '0x5': {'0x3': 1.0}},
"[2, 0]": {'0x2': {'0x0': 1.0}, '0x5': {'0x3': 1.0}},
"[1, 2]": {'0x2': {'0x1': 1.0}, '0x5': {'0x2': 1.0}},
"[2, 1]": {'0x2': {'0x2': 1.0}, '0x5': {'0x1': 1.0}},
"[0, 1, 2]": {'0x2': {'0x2': 1.0}, '0x5': {'0x5': 1.0}},
"[1, 2, 0]": {'0x2': {'0x1': 1.0}, '0x5': {'0x6': 1.0}},
"[2, 0, 1]": {'0x2': {'0x4': 1.0}, '0x5': {'0x3': 1.0}},
}
targets.append(probs)
return targets

0 comments on commit 711c215

Please sign in to comment.