Skip to content

Commit

Permalink
Merge branch 'main' into docs/md_docs
Browse files Browse the repository at this point in the history
  • Loading branch information
CalMacCQ authored Oct 24, 2024
2 parents 742cc87 + 577b9a0 commit 65c68b8
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 13 deletions.
9 changes: 8 additions & 1 deletion pytket/extensions/qiskit/backends/aer.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,14 @@ def get_result(self, handle: ResultHandle, **kwargs: KwargTypes) -> BackendResul
raise CircuitNotRunError(handle)

res = job.result()
backresults = qiskit_result_to_backendresult(res)
backresults = qiskit_result_to_backendresult(
res,
include_shots=self._supports_shots,
include_counts=self._supports_counts,
include_state=self._supports_state,
include_unitary=self._supports_unitary,
include_density_matrix=self._supports_density_matrix,
)
for circ_index, backres in enumerate(backresults):
self._cache[ResultHandle(jobid, circ_index, qubit_n, ppc)][
"result"
Expand Down
44 changes: 33 additions & 11 deletions pytket/extensions/qiskit/result_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from qiskit.result import Result # type: ignore
from qiskit.result.models import ExperimentResult # type: ignore

from pytket.circuit import Bit, Qubit, UnitID, Circuit
from pytket.circuit import Bit, Qubit, UnitID

from pytket.backends.backendresult import BackendResult
from pytket.utils.outcomearray import OutcomeArray
Expand Down Expand Up @@ -81,9 +81,17 @@ def _result_is_empty_shots(result: ExperimentResult) -> bool:
return False


# In some cases, Qiskit returns a result with fields we don't expect -
# for example, a circuit with classical bits run on AerStateBackend will
# return counts (whether or not there were measurements). The include_foo
# arguments should be set based on what the backend supports.
def qiskit_experimentresult_to_backendresult(
result: ExperimentResult,
ppcirc: Optional[Circuit] = None,
include_counts: bool = True,
include_shots: bool = True,
include_state: bool = True,
include_unitary: bool = True,
include_density_matrix: bool = True,
) -> BackendResult:
if not result.success:
raise RuntimeError(result.status)
Expand All @@ -105,16 +113,16 @@ def qiskit_experimentresult_to_backendresult(

shots, counts, state, unitary, density_matrix = (None,) * 5
datadict = result.data.to_dict()
if _result_is_empty_shots(result):
if _result_is_empty_shots(result) and include_shots:
n_bits = len(c_bits) if c_bits else 0
shots = OutcomeArray.from_readouts(
np.zeros((result.shots, n_bits), dtype=np.uint8)
)
else:
if "memory" in datadict:
if "memory" in datadict and include_shots:
memory = datadict["memory"]
shots = _hex_to_outar(memory, width)
elif "counts" in datadict:
elif "counts" in datadict and include_counts:
qis_counts = datadict["counts"]
counts = Counter(
dict(
Expand All @@ -123,13 +131,13 @@ def qiskit_experimentresult_to_backendresult(
)
)

if "statevector" in datadict:
if "statevector" in datadict and include_state:
state = datadict["statevector"].reverse_qargs().data

if "unitary" in datadict:
if "unitary" in datadict and include_unitary:
unitary = datadict["unitary"].reverse_qargs().data

if "density_matrix" in datadict:
if "density_matrix" in datadict and include_density_matrix:
density_matrix = datadict["density_matrix"].reverse_qargs().data

return BackendResult(
Expand All @@ -140,13 +148,27 @@ def qiskit_experimentresult_to_backendresult(
state=state,
unitary=unitary,
density_matrix=density_matrix,
ppcirc=ppcirc,
ppcirc=None,
)


def qiskit_result_to_backendresult(res: Result) -> Iterator[BackendResult]:
def qiskit_result_to_backendresult(
res: Result,
include_counts: bool = True,
include_shots: bool = True,
include_state: bool = True,
include_unitary: bool = True,
include_density_matrix: bool = True,
) -> Iterator[BackendResult]:
for result in res.results:
yield qiskit_experimentresult_to_backendresult(result)
yield qiskit_experimentresult_to_backendresult(
result,
include_counts,
include_shots,
include_state,
include_unitary,
include_density_matrix,
)


def backendresult_to_qiskit_resultdata(
Expand Down
7 changes: 6 additions & 1 deletion tests/qiskit_convert_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,12 +549,17 @@ def test_convert_result() -> None:
qc1.save_state()
qisk_result = simulator.run(qc1, shots=10).result()

tk_res = next(qiskit_result_to_backendresult(qisk_result))
# exclude counts from result (we don't expect them
# for the statevector sim after all)
tk_res = next(qiskit_result_to_backendresult(qisk_result, include_counts=False))

state = tk_res.get_state([Qubit("q2", 1), Qubit("q1", 0), Qubit("q2", 0)])
correct_state = np.zeros(1 << 3, dtype=complex)
correct_state[6] = 1 + 0j
assert compare_statevectors(state, correct_state)
# also check that we don't return counts in tket result
# even if the qiskit result includes them
assert tk_res._counts is None

# check measured
qc.measure(qr1[0], cr[0])
Expand Down

0 comments on commit 65c68b8

Please sign in to comment.