from datetime import timedelta
import pickle
import pytest
import numpy as np
from numpy.testing import assert_array_equal
from qcs_sdk import QcsSdkError
from qcs_sdk.qpu import ReadoutValues, MemoryValues, QPUResultData
from qcs_sdk.qvm import QVMResultData
from qcs_sdk import RegisterData, RegisterMatrix, ExecutionData
class TestResultData:
def test_to_register_map_from_qpu_result_data(self):
mappings = {
"ro[0]": "qA",
"ro[1]": "qB",
"ro[2]": "qC",
}
readout_values = {
"qA": ReadoutValues.Integer([0, 1]),
"qB": ReadoutValues.Integer([1, 2]),
"qC": ReadoutValues.Integer([2, 3]),
}
memory_values = {
"ro": MemoryValues.Integer([1, 2, 3]),
}
result_data = QPUResultData(mappings, readout_values, memory_values)
register_map = result_data.to_register_map()
ro = register_map.get_register_matrix("ro")
assert ro is not None, "'ro' should exist in the register map"
match ro:
case RegisterMatrix.Integer(ro):
pass
case _:
pytest.fail(f"unexpected register matrix type: {type(ro)}")
assert ro is not None, "'ro' should be an integer register matrix"
expected = np.array([[0, 1, 2], [1, 2, 3]])
assert_array_equal(ro, expected)
def test_to_register_map_from_jagged_qpu_result_data(self):
mappings = {
"ro[0]": "qA",
"ro[1]": "qB",
"ro[2]": "qC",
}
values = {
"qA": ReadoutValues.Integer([0, 1]),
"qB": ReadoutValues.Integer([1]),
"qC": ReadoutValues.Integer([2, 3]),
}
result_data = QPUResultData(mappings, values, {})
with pytest.raises(QcsSdkError):
result_data.to_register_map()
def test_to_register_map_from_qvm_result_data(self):
qvm_memory_map = {"ro": RegisterData.I16([[0, 1, 2], [1, 2, 3]])}
result_data = QVMResultData.from_memory_map(qvm_memory_map)
register_map = result_data.to_register_map()
ro = register_map.get_register_matrix("ro")
assert ro is not None, "'ro' should exist in the register map"
match ro:
case RegisterMatrix.Integer(ro):
pass
case _:
pytest.fail(f"unexpected register matrix type: {type(ro)}")
assert ro is not None, "'ro' should be an integer register matrix"
expected = np.array([[0, 1, 2], [1, 2, 3]])
assert_array_equal(ro, expected)
@pytest.mark.parametrize(
("name", "m", "cls"),
[
("integer", np.array([[0, 1, 2], [1, 2, 3]]), RegisterMatrix.Integer),
("real", np.array([[0.0, 1.1, 2.2], [1.1, 2.2, 3.3]]), RegisterMatrix.Real),
("complex",
np.array([[complex(0, 1), complex(1, 2), complex(2, 3)],
[complex(1, 2), complex(2, 3), complex(3, 4)]]),
RegisterMatrix.Complex),
]
)
def test_register_matrix(name: str, m: np.ndarray, cls: RegisterMatrix.Integer | RegisterMatrix.Real | RegisterMatrix.Complex):
register_matrix = cls(m)
match (name, register_matrix):
case ("integer", RegisterMatrix.Integer(register_matrix)):
pass
case ("real", RegisterMatrix.Real(register_matrix)):
pass
case ("complex", RegisterMatrix.Complex(register_matrix)):
pass
case _:
pytest.fail(f"unexpected register_matrix type: {type(register_matrix)}")
assert register_matrix is not None, f"register_matrix should be an {name} matrix"
assert_array_equal(register_matrix, m)
class TestRegisterMap:
def test_iter(self):
memory_map = {
"ro": RegisterData.I16([[0, 1, 2], [1, 2, 3]]),
"foo": RegisterData.I16([[0, 1, 2], [1, 2, 3]]),
}
result_data = QVMResultData.from_memory_map(memory_map)
register_map = result_data.to_register_map()
expected_keys = {"ro", "foo"}
actual_keys = set()
for key, matrix in register_map.items():
actual_keys.add(key)
assert np.all(matrix.to_ndarray() == np.array([[0, 1, 2], [1, 2, 3]]))
assert expected_keys == actual_keys == set(register_map.keys())
class TestExecutionData:
def test_pickle(self):
qpu_result_data = QPUResultData(
mappings={"q0": "ro"},
readout_values={"q0": ReadoutValues([0, 1])},
memory_values={"m": MemoryValues([0, 1])},
)
qvm_result_data = QVMResultData.from_memory_map({"ro": RegisterData([[0, 1]])})
for execution_data in [
ExecutionData(result_data=qpu_result_data, duration=timedelta(seconds=1)),
ExecutionData(result_data=qvm_result_data, duration=None),
]:
print(execution_data.result_data)
pickled = pickle.dumps(execution_data)
unpickled = pickle.loads(pickled)
assert execution_data == unpickled