Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

job/result: expose raw bitstrings through result.get_memory() #48

Merged
merged 1 commit into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

* Expose the result polling period and timeout as backend options #46
* Support `qiskit.result.Result.get_memory()` to retrieve the raw results bitstrings #48

## qiskit-aqt-provider v0.10.0

Expand Down
6 changes: 5 additions & 1 deletion qiskit_aqt_provider/aqt_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from dataclasses import dataclass
from typing import (
TYPE_CHECKING,
Any,
ClassVar,
DefaultDict,
Dict,
Expand Down Expand Up @@ -151,11 +152,14 @@ def result(self) -> Result:

# jobs order is submission order
for circuit, result in zip(self.circuits, self._jobs.values()):
data = {}
data: Dict[str, Any] = {}

if isinstance(result, JobFinished):
meas_map = _build_memory_mapping(circuit)
data["counts"] = _format_counts(result.samples, meas_map)
data["memory"] = [
"".join(str(x) for x in reversed(shots)) for shots in result.samples
]

results.append(
{
Expand Down
2 changes: 1 addition & 1 deletion qiskit_aqt_provider/aqt_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def __init__(self, provider: Provider, workspace: str, resource: ApiResource):
"coupling_map": None,
"description": "AQT trapped-ion device simulator",
"basis_gates": ["r", "rz", "rxx"], # the actual basis gates
"memory": False,
"memory": True,
"n_qubits": num_qubits,
"conditional": False,
"max_shots": 200,
Expand Down
63 changes: 63 additions & 0 deletions test/test_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from dirty_equals import IsUUID
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister
from qiskit.result import Counts
from qiskit_aer import AerSimulator
from qiskit_experiments.library import QuantumVolume

from qiskit_aqt_provider.aqt_resource import AQTResource
Expand Down Expand Up @@ -133,6 +134,68 @@ def test_multiple_classical_registers(shots: int, offline_simulator_no_noise: AQ
assert job.result().get_counts() == {"010 01": shots}


@pytest.mark.parametrize("shots", [123])
@pytest.mark.parametrize("memory_opt", [True, False])
def test_get_memory_simple(
shots: int, memory_opt: bool, offline_simulator_no_noise: AQTResource
) -> None:
"""Check that the raw bitstrings can be accessed for each shot via the
get_memory() method in Qiskit's Result.

The memory option has no effect (raw memory is always accessible)."""
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

result = qiskit.execute(qc, offline_simulator_no_noise, shots=shots, memory=memory_opt).result()
memory = result.get_memory()

assert set(memory) == {"11", "00"}
assert len(memory) == shots


@pytest.mark.parametrize("shots", [123])
def test_get_memory_ancilla_qubits(shots: int, offline_simulator_no_noise: AQTResource) -> None:
"""Check that the raw bistrings returned by get_memory() in Qiskit's Result only
contain the mapped classical bits."""
qr = QuantumRegister(2)
qr_aux = QuantumRegister(3)
memory = ClassicalRegister(2)

qc = QuantumCircuit(qr, qr_aux, memory)
qc.rx(pi, qr[0])
qc.ry(pi, qr[1])
qc.rxx(pi / 2, qr_aux[0], qr_aux[1])
qc.measure(qr, memory)

job = qiskit.execute(qc, offline_simulator_no_noise, shots=shots)
memory = job.result().get_memory()

assert set(memory) == {"11"}
assert len(memory) == shots


@pytest.mark.parametrize("shots", [123])
def test_get_memory_bit_ordering(shots: int, offline_simulator_no_noise: AQTResource) -> None:
"""Check that the bitstrings returned by the results produced by AQT jobs have the same
bit order as the Qiskit Aer simulators."""
sim = AerSimulator(method="statevector")

qc = QuantumCircuit(3)
qc.rx(pi, 0)
qc.rx(pi, 1)
qc.measure_all()

aqt_memory = qiskit.execute(qc, offline_simulator_no_noise, shots=shots).result().get_memory()
sim_memory = qiskit.execute(qc, sim, shots=shots, memory=True).result().get_memory()

assert set(sim_memory) == set(aqt_memory)

# sanity check: bitstrings are no palindromes
assert not any(bitstring == bitstring[::-1] for bitstring in sim_memory)


@pytest.mark.parametrize("shots,qubits", [(100, 5), (100, 8)])
def test_bell_states(shots: int, qubits: int, offline_simulator_no_noise: AQTResource) -> None:
"""Create a N qubits Bell state."""
Expand Down