Skip to content

Commit

Permalink
fix: Emit nested binary expressions for classical ops (#224)
Browse files Browse the repository at this point in the history
* test: add test for issue 215

* docs: provide maintainer email ID
Closes: #142

* chore: update deps

* fix: generate nested multi-bit conditions for pecos support

* test: remove dependency on pecos and more granular test

* refactor: raise TypeError on passing less than min_args

* refactor: use `min_args` in the error message

Co-authored-by: Alec Edgington <[email protected]>

---------

Co-authored-by: Alec Edgington <[email protected]>
  • Loading branch information
qartik and cqc-alec authored Sep 11, 2024
1 parent ddbb5cc commit e9863b6
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 17 deletions.
11 changes: 6 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ name = "pytket-phir"
description = "A circuit analyzer and translator from pytket to PHIR"
readme = "README.md"
requires-python = ">=3.10, <3.13"
license = {file = "LICENSE"}
authors = [{name = "Quantinuum"}]
license = { file = "LICENSE" }
authors = [{ name = "Quantinuum" }]
maintainers = [
{ name = "Kartik Singhal", email = "[email protected]" },
]

classifiers = [
"Environment :: Console",
Expand Down Expand Up @@ -50,9 +53,7 @@ where = ["."]

[tool.pytest.ini_options]
addopts = "-s -vv"
pythonpath = [
"."
]
pythonpath = ["."]
log_cli = true
log_cli_level = "INFO"
log_level = "DEBUG"
Expand Down
33 changes: 24 additions & 9 deletions pytket/phir/phirgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import json
import logging
import sys
from collections import deque
from copy import deepcopy
from importlib.metadata import version
from typing import TYPE_CHECKING, Any, TypeAlias
Expand Down Expand Up @@ -356,15 +357,29 @@ def convert_classicalevalop(op: tk.ClassicalEvalOp, cmd: tk.Command) -> JsonDict

def multi_bit_condition(args: "list[UnitID]", value: int) -> JsonDict:
"""Construct bitwise condition."""
return {
"cop": "&",
"args": [
{"cop": "==", "args": [arg_to_bit(arg), bval]}
for (arg, bval) in zip(
args[::-1], map(int, f"{value:0{len(args)}b}"), strict=True
)
],
}
min_args = 2
if len(args) < min_args:
msg = f"multi_bit_condition requires at least {min_args} arguments"
raise TypeError(msg)

def nested_cop(cop: str, args: "deque[UnitID]", val_bits: deque[int]) -> JsonDict:
if len(args) == min_args:
return {
"cop": cop,
"args": [
{"cop": "==", "args": [arg_to_bit(args.popleft()), val_bits.pop()]},
{"cop": "==", "args": [arg_to_bit(args.popleft()), val_bits.pop()]},
],
}
return {
"cop": cop,
"args": [
{"cop": "==", "args": [arg_to_bit(args.popleft()), val_bits.pop()]},
nested_cop(cop, args, val_bits),
],
}

return nested_cop("&", deque(args), deque(map(int, f"{value:0{len(args)}b}")))


def convert_subcmd(op: tk.Op, cmd: tk.Command) -> JsonDict | None: # noqa: PLR0912
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ networkx<3
phir==0.3.3
pre-commit==3.8.0
pydata_sphinx_theme==0.15.4
pytest==8.3.2
pytest==8.3.3
pytket==1.32.0
ruff==0.6.4
setuptools_scm==8.1.0
Expand Down
27 changes: 25 additions & 2 deletions tests/test_phirgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def test_pytket_classical_only() -> None:
"condition": {
"cop": "&",
"args": [
{"cop": "==", "args": [["b", 2], 1]},
{"cop": "==", "args": [["b", 1], 0]},
{"cop": "==", "args": [["b", 2], 1]},
],
},
"true_branch": [
Expand Down Expand Up @@ -177,8 +177,8 @@ def test_conditional_barrier() -> None:
"condition": {
"cop": "&",
"args": [
{"cop": "==", "args": [["m", 1], 0]},
{"cop": "==", "args": [["m", 0], 0]},
{"cop": "==", "args": [["m", 1], 0]},
],
},
"true_branch": [{"meta": "barrier", "args": [["q", 0], ["q", 1]]}],
Expand Down Expand Up @@ -463,3 +463,26 @@ def test_nullary_ops() -> None:
"cop": "==",
"args": [["tk_SCRATCH_BIT", 1], 1], # evals to False
}


def test_condition_multiple_bits() -> None:
"""From https://github.com/CQCL/pytket-phir/issues/215 ."""
n_bits = 3
c = Circuit(1, n_bits)
c.Rz(0.5, 0, condition_bits=list(range(n_bits)), condition_value=6)
phir = json.loads(pytket_to_phir(c))

assert phir["ops"][2] == {"//": "IF ([c[0], c[1], c[2]] == 6) THEN Rz(0.5) q[0];"}
assert phir["ops"][3]["condition"] == {
"cop": "&",
"args": [
{"cop": "==", "args": [["c", 0], 0]},
{
"cop": "&",
"args": [
{"cop": "==", "args": [["c", 1], 1]},
{"cop": "==", "args": [["c", 2], 1]},
],
},
],
}

0 comments on commit e9863b6

Please sign in to comment.