From f2f79471b472217ef1e8b63f69f4ad1491d4cd93 Mon Sep 17 00:00:00 2001 From: Hayk Sargsyan <52532457+hay-k@users.noreply.github.com> Date: Wed, 2 Oct 2024 17:41:51 +0400 Subject: [PATCH 1/4] Make RB circuits actually random --- src/qibocal/protocols/randomized_benchmarking/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qibocal/protocols/randomized_benchmarking/utils.py b/src/qibocal/protocols/randomized_benchmarking/utils.py index 381056e8f..fd4535509 100644 --- a/src/qibocal/protocols/randomized_benchmarking/utils.py +++ b/src/qibocal/protocols/randomized_benchmarking/utils.py @@ -601,14 +601,14 @@ def layer_circuit( random_indexes = [] if isinstance(target, (str, int)): nqubits = 1 - rb_gen_layer = rb_gen.layer_gen_single_qubit() + rb_gen_layer = rb_gen.layer_gen_single_qubit elif isinstance(target, Tuple): # Tuple for qubit pair nqubits = 2 - rb_gen_layer = rb_gen.layer_gen_two_qubit() + rb_gen_layer = rb_gen.layer_gen_two_qubit # Build each layer, there will be depth many in the final circuit. for _ in range(depth): # Generate a layer. - new_layer, random_index = rb_gen_layer + new_layer, random_index = rb_gen_layer() random_indexes.append(random_index) new_circuit = Circuit(nqubits) if nqubits == 1: From 48bd6b17cc4cc0f5e86126216f1b6236d2cd5dd0 Mon Sep 17 00:00:00 2001 From: Hayk Sargsyan <52532457+hay-k@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:37:39 +0400 Subject: [PATCH 2/4] RB circuit layer generation tests --- poetry.lock | 19 ++++++++++- pyproject.toml | 1 + tests/test_randomized_benchmarking.py | 45 +++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index deb03225e..e6778687a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2493,6 +2493,23 @@ pytest = ">=7.3.1" [package.extras] test = ["coverage (>=7.2.7)", "pytest-mock (>=3.10)"] +[[package]] +name = "pytest-mock" +version = "3.14.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -3404,4 +3421,4 @@ viz = ["pydot"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "878af869bce716692424a4ff967715148795b05aecfddedeab83ae0418a649d4" +content-hash = "ca3b3838087ba97df70a82e21044f440b01310f7e7a73819449915d1c499f7f2" diff --git a/pyproject.toml b/pyproject.toml index 49f984644..f75b491e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,6 +46,7 @@ pylint = "^2.17" pytest = "^7.1.2" pytest-cov = "^3.0.0" pytest-env = "^0.8.1" +pytest-mock = "^3.14.0" [tool.poetry.group.docs] optional = true diff --git a/tests/test_randomized_benchmarking.py b/tests/test_randomized_benchmarking.py index 0baab439b..78defac7b 100644 --- a/tests/test_randomized_benchmarking.py +++ b/tests/test_randomized_benchmarking.py @@ -9,6 +9,7 @@ from qibocal.protocols.randomized_benchmarking.utils import ( RB_Generator, generate_inv_dict_cliffords_file, + layer_circuit, load_cliffords, random_clifford, ) @@ -184,3 +185,47 @@ def test_generate_inv_dict_cliffords_file(tmp_path): clifford_matrices_inv = load_inverse_cliffords(file_inv) assert clifford_inv.files == clifford_matrices_inv.files + + +@pytest.mark.parametrize("depth", [1, 10, 34]) +def test_layer_circuit_single_qubit(mocker, depth): + qubit = 0 + rb_gen = RB_Generator(123) + single_qubit_spy = mocker.spy(rb_gen, 'layer_gen_single_qubit') + two_qubit_spy = mocker.spy(rb_gen, 'layer_gen_two_qubit') + + circuit, indices = layer_circuit(rb_gen, depth, qubit) + + # assert that generator was called expected number of times + assert single_qubit_spy.call_count == depth + assert two_qubit_spy.call_count == 0 + + # assert that results from generator calls were used + assert circuit.depth == depth + circuit_gates = {g for m in circuit.queue.moments for g in m} + indices = set(indices) + for gate, i in single_qubit_spy.spy_return_list: + assert gate in circuit_gates + assert i in indices + + +@pytest.mark.parametrize("depth", [2, 24, 47]) +def test_layer_circuit_two_qubit(mocker, depth): + qubit_pair = (0, 1) + rb_gen = RB_Generator(123, file="2qubitCliffs.json") + single_qubit_spy = mocker.spy(rb_gen, 'layer_gen_single_qubit') + two_qubit_spy = mocker.spy(rb_gen, 'layer_gen_two_qubit') + + circuit, indices = layer_circuit(rb_gen, depth, qubit_pair) + + # assert that generator was called expected number of times + assert single_qubit_spy.call_count == 0 + assert two_qubit_spy.call_count == depth + + # assert that results from generator calls were used + assert circuit.depth >= depth + circuit_gates = [g for m in circuit.queue.moments for g in m if g is not None] + indices = set(indices) + for gates, i in two_qubit_spy.spy_return_list: + assert all(g in circuit_gates for g in gates) + assert i in indices From c105292591a805b75523bfe1f092e821a67be357 Mon Sep 17 00:00:00 2001 From: Hayk Sargsyan <52532457+hay-k@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:40:47 +0400 Subject: [PATCH 3/4] fix type annotation --- src/qibocal/protocols/randomized_benchmarking/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibocal/protocols/randomized_benchmarking/utils.py b/src/qibocal/protocols/randomized_benchmarking/utils.py index fd4535509..e9f41ced3 100644 --- a/src/qibocal/protocols/randomized_benchmarking/utils.py +++ b/src/qibocal/protocols/randomized_benchmarking/utils.py @@ -585,7 +585,7 @@ def twoq_rb_acquisition( def layer_circuit( rb_gen: Callable, depth: int, target, interleave: str = None -) -> tuple[Circuit, dict]: +) -> tuple[Circuit, list]: """Creates a circuit of `depth` layers from a generator `layer_gen` yielding `Circuit` or `Gate` and a dictionary with random indexes used to select the clifford gates. From 4704913435668e0e5017edc3e48cd57765e99695 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 07:48:38 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_randomized_benchmarking.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_randomized_benchmarking.py b/tests/test_randomized_benchmarking.py index 78defac7b..86e87bb39 100644 --- a/tests/test_randomized_benchmarking.py +++ b/tests/test_randomized_benchmarking.py @@ -191,9 +191,9 @@ def test_generate_inv_dict_cliffords_file(tmp_path): def test_layer_circuit_single_qubit(mocker, depth): qubit = 0 rb_gen = RB_Generator(123) - single_qubit_spy = mocker.spy(rb_gen, 'layer_gen_single_qubit') - two_qubit_spy = mocker.spy(rb_gen, 'layer_gen_two_qubit') - + single_qubit_spy = mocker.spy(rb_gen, "layer_gen_single_qubit") + two_qubit_spy = mocker.spy(rb_gen, "layer_gen_two_qubit") + circuit, indices = layer_circuit(rb_gen, depth, qubit) # assert that generator was called expected number of times @@ -213,9 +213,9 @@ def test_layer_circuit_single_qubit(mocker, depth): def test_layer_circuit_two_qubit(mocker, depth): qubit_pair = (0, 1) rb_gen = RB_Generator(123, file="2qubitCliffs.json") - single_qubit_spy = mocker.spy(rb_gen, 'layer_gen_single_qubit') - two_qubit_spy = mocker.spy(rb_gen, 'layer_gen_two_qubit') - + single_qubit_spy = mocker.spy(rb_gen, "layer_gen_single_qubit") + two_qubit_spy = mocker.spy(rb_gen, "layer_gen_two_qubit") + circuit, indices = layer_circuit(rb_gen, depth, qubit_pair) # assert that generator was called expected number of times