From e98abf3a0b6b3913df5daf331e85e7e561e2e496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20Ryan-Anderson?= <70174051+qciaran@users.noreply.github.com> Date: Wed, 13 Dec 2023 14:54:35 -0700 Subject: [PATCH] Added support for qparallel. (#33) * Added support for qparallel. * Bumping to 0.5.0.dev4 --- pyproject.toml | 4 ++-- python/pecos/reps/pypmir/block_types.py | 14 +++++++++++--- python/pecos/reps/pypmir/pypmir.py | 9 +++++++++ requirements.txt | 4 ++-- tests/integration/phir/qparallel.json | 19 +++++++++++++++++++ tests/integration/test_phir.py | 12 ++++++++++++ 6 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 tests/integration/phir/qparallel.json diff --git a/pyproject.toml b/pyproject.toml index 3e4d5e5b..07debada 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ build-backend = "setuptools.build_meta" [project] name = "quantum-pecos" -version = "0.5.0.dev3" +version = "0.5.0.dev4" authors = [ {name = "The PECOS Developers"}, ] @@ -28,7 +28,7 @@ requires-python = ">=3.10" license = { file = "LICENSE"} keywords = ["quantum", "QEC", "simulation", "PECOS"] dependencies = [ - "phir~=0.1.6", + "phir~=0.2.1", "numpy>=1.15.0,<2.0", "scipy>=1.1.0,<2.0", "networkx>=2.1.0,<3.0", diff --git a/python/pecos/reps/pypmir/block_types.py b/python/pecos/reps/pypmir/block_types.py index a5094472..2cf889d7 100644 --- a/python/pecos/reps/pypmir/block_types.py +++ b/python/pecos/reps/pypmir/block_types.py @@ -14,7 +14,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from pecos.reps.pypmir.op_types import COp + from pecos.reps.pypmir.op_types import COp, Op, QOp class Block: @@ -25,13 +25,21 @@ def __init__(self, metadata: dict | None = None) -> None: class SeqBlock(Block): - """A generic sequence block.""" + """A generic sequence block. This is not meant to indicate parallelism or lack of it but is just a way to structure + operations/blocks.""" - def __init__(self, ops: list, metadata: dict | None = None) -> None: + def __init__(self, ops: list[Op | Block], metadata: dict | None = None) -> None: super().__init__(metadata=metadata) self.ops = ops +class QParallelBlock(SeqBlock): + """A block to indicate that a collection of QOps are applied in parallel.""" + + def __init__(self, ops: list[QOp], metadata: dict | None = None) -> None: + super().__init__(ops=ops, metadata=metadata) + + class IfBlock(Block): """If/else block.""" diff --git a/python/pecos/reps/pypmir/pypmir.py b/python/pecos/reps/pypmir/pypmir.py index 1cb7fce2..a8329514 100644 --- a/python/pecos/reps/pypmir/pypmir.py +++ b/python/pecos/reps/pypmir/pypmir.py @@ -51,6 +51,15 @@ def handle_op(cls, o: dict, p: PyPMIR) -> TypeOp: ops=ops, metadata=o.get("metadata"), ) + elif o["block"] == "qparallel": + ops = [] + for so in o["ops"]: + ops.append(cls.handle_op(so, p)) + + instr = blk.QParallelBlock( + ops=ops, + metadata=o.get("metadata"), + ) elif o["block"] == "if": true_branch = [] for so in o["true_branch"]: diff --git a/requirements.txt b/requirements.txt index d178edd2..d2c16a29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,7 @@ mdurl==0.1.2 networkx==2.8.8 numpy==1.26.2 packaging==23.2 -phir==0.1.6 +phir==0.2.1 pillow==10.1.0 pluggy==1.3.0 pydantic==2.5.2 @@ -29,4 +29,4 @@ python-dateutil==2.8.2 rich==13.7.0 scipy==1.11.4 six==1.16.0 -typing-extensions==4.8.0 +typing-extensions==4.9.0 diff --git a/tests/integration/phir/qparallel.json b/tests/integration/phir/qparallel.json new file mode 100644 index 00000000..822620bb --- /dev/null +++ b/tests/integration/phir/qparallel.json @@ -0,0 +1,19 @@ +{ + "format": "PHIR/JSON", + "version": "0.1.0", + "metadata": {}, + "ops": [ + {"data": "qvar_define", "data_type": "qubits", "variable": "q", "size": 4}, + {"data": "cvar_define", "data_type": "u32", "variable": "m", "size": 4}, + { + "block": "qparallel", + "ops": [ + {"qop": "X", "args": [["q", 1], ["q", 3]]}, + {"qop": "Y", "args": [["q", 0], ["q", 2]]} + ] + }, + {"qop": "Measure", + "returns": [["m", 0], ["m", 1], ["m", 2], ["m", 3]], + "args": [["q", 0], ["q", 1], ["q", 2], ["q", 3]]} + ] +} diff --git a/tests/integration/test_phir.py b/tests/integration/test_phir.py index 2cff39ab..aae33b5f 100644 --- a/tests/integration/test_phir.py +++ b/tests/integration/test_phir.py @@ -248,3 +248,15 @@ def test_throw_exception_with_bad_phir(): phir = json.load(Path.open(this_dir / "phir" / "bad_phir.json")) with pytest.raises(ValidationError): PHIRModel.model_validate(phir) + + +def test_qparallel(): + """Testing the qparallel block of 2 Xs and 2 Ys gives an output of 1111.""" + + results = HybridEngine(qsim="stabilizer").run( + program=json.load(Path.open(this_dir / "phir" / "qparallel.json")), + shots=10, + ) + + m = results["m"] + assert m.count("1111") == len(m)