Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(barrier): add support for barrier meta instruction #56

Merged
merged 4 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ repos:
- black==23.10.1

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.14
rev: v0.1.15
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand Down
26 changes: 22 additions & 4 deletions phir/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ class ExportVar(Data):

DataMgmt: TypeAlias = CVarDefine | QVarDefine | ExportVar

# Meta Instructions


class Meta(BaseModel, abc.ABC):
"""Meta instructions base class."""

model_config = ConfigDict(extra="forbid")

meta: str


class Barrier(Meta):
"""Barrier instruction."""

meta: Literal["barrier"]
args: list[Bit]


# Operations


Expand Down Expand Up @@ -243,14 +261,14 @@ class MOp(Op):


QOp: TypeAlias = MeasOp | SQOp | TQOp
OpType: TypeAlias = FFCall | COp | QOp | MOp
OpType: TypeAlias = FFCall | COp | QOp | MOp | Barrier
Copy link
Member Author

@qartik qartik Jan 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required to be able to treat Barrier as, e.g., an op under a conditional. See CQCL/pytket-phir#119



# Blocks


class Block(BaseModel, abc.ABC):
"""General block type."""
"""Base class for block type."""

model_config = ConfigDict(extra="forbid")

Expand All @@ -277,8 +295,8 @@ class IfBlock(Block):

block: Literal["if"]
condition: COp
true_branch: list[OpType]
false_branch: list[OpType] | None = None
true_branch: list[OpType | BlockType]
false_branch: list[OpType | BlockType] | None = None


BlockType: TypeAlias = SeqBlock | QParBlock | IfBlock
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ autodoc-pydantic==2.0.1
build==1.0.3
mypy==1.8.0
pre-commit==3.6.0
pydantic==2.5.3
pydantic==2.6.0
pydata_sphinx_theme==0.15.2
pytest==8.0.0
rich==13.7.0
ruff==0.1.14
ruff==0.1.15
setuptools-scm==8.0.4
sphinx==7.2.6
wheel==0.42.0
4 changes: 2 additions & 2 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ select = [
"YTT", # flake8-2020
]

ignore = ["COM812", "ISC001"] # conflicting with the formatter

[per-file-ignores]
"__init__.py" = ["F401", "CPY001"]
"docs/*" = [
Expand All @@ -71,8 +73,6 @@ select = [
"INP001",
]

ignore = ["COM812", "ISC001"] # conflicting with the formatter

[pydocstyle]
convention = "google"

Expand Down
64 changes: 64 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
{
"$defs": {
"Barrier": {
"additionalProperties": false,
"description": "Barrier instruction.",
"properties": {
"meta": {
"const": "barrier",
"title": "Meta"
},
"args": {
"items": {
"maxItems": 2,
"minItems": 2,
"prefixItems": [
{
"type": "string"
},
{
"minimum": 0,
"type": "integer"
}
],
"type": "array"
},
"title": "Args",
"type": "array"
}
},
"required": [
"meta",
"args"
],
"title": "Barrier",
"type": "object"
},
"COp": {
"additionalProperties": false,
"description": "Classical operation.",
Expand Down Expand Up @@ -374,6 +408,18 @@
},
{
"$ref": "#/$defs/MOp"
},
{
"$ref": "#/$defs/Barrier"
},
{
"$ref": "#/$defs/SeqBlock"
},
{
"$ref": "#/$defs/QParBlock"
},
{
"$ref": "#/$defs/IfBlock"
}
]
},
Expand Down Expand Up @@ -402,6 +448,18 @@
},
{
"$ref": "#/$defs/MOp"
},
{
"$ref": "#/$defs/Barrier"
},
{
"$ref": "#/$defs/SeqBlock"
},
{
"$ref": "#/$defs/QParBlock"
},
{
"$ref": "#/$defs/IfBlock"
}
]
},
Expand Down Expand Up @@ -776,6 +834,9 @@
{
"$ref": "#/$defs/MOp"
},
{
"$ref": "#/$defs/Barrier"
},
{
"$ref": "#/$defs/SeqBlock"
},
Expand Down Expand Up @@ -966,6 +1027,9 @@
{
"$ref": "#/$defs/MOp"
},
{
"$ref": "#/$defs/Barrier"
},
{
"$ref": "#/$defs/SeqBlock"
},
Expand Down
18 changes: 18 additions & 0 deletions spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,24 @@ bitwise/logical operations, or comparisons between two variables and/or bits. In
*Note:* While PHIR/PECOS can effectively manage nested if/else statements, extended OpenQASM 2.0 strictly permits only
non-nested if statements. Consequently, such nesting should be sidestepped when converting from OpenQASM 2.0 to PHIR.

## Meta Instructions

Instructions that communicate information such as a compiler hints and debugging commands that have influence beyond
a quantum program.

### Barrier

A barrier instruction provides a hint to the compiler/emulator that qubits involved in barrier may not be optimized or
parallelized across the barrier. Effectively, it enforces an ordering in time for how quantum state is manipulated by
the machine.

```json5
{
"meta": "barrier",
"args": [qubit_id, ...] // list of qubit IDs
}
```

## Overall PHIR Example with Quantinuum's Extended OpenQASM 2.0

A simple quantum program might look like:
Expand Down
54 changes: 54 additions & 0 deletions tests/cond_barrier_qparallel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"format": "PHIR/JSON",
"version": "0.1.0",
"metadata": { "strict_parallelism": "true" },
"ops": [
{
"data": "qvar_define",
"data_type": "qubits",
"variable": "q",
"size": 2
},
{ "data": "cvar_define", "data_type": "u32", "variable": "m", "size": 2 },
{
"block": "sequence",
"ops": [
{
"block": "if",
"condition": { "cop": "==", "args": ["m", 0] },
"true_branch": [
{
"meta": "barrier",
"args": [
["q", 0],
["q", 1]
]
}
]
},
{
"block": "if",
"condition": { "cop": "==", "args": ["m", 1] },
"true_branch": [
{
"block": "qparallel",
"ops": [
{ "qop": "SZdg", "args": [["q", 0]] },
{ "qop": "SZ", "args": [["q", 1]] }
]
}
],
"false_branch": [
{
"block": "qparallel",
"ops": [
{ "qop": "SZdg", "args": [["q", 0]] },
{ "qop": "SZ", "args": [["q", 1]] }
]
}
]
}
]
}
]
}
21 changes: 17 additions & 4 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#
##############################################################################

# mypy: disable-error-code="misc"

"""Basic validation tests."""

import json
Expand All @@ -14,9 +16,20 @@
from phir.model import PHIRModel


def test_spec_example() -> None: # noqa: D103
# From https://github.com/CQCL/phir/blob/main/spec.md#overall-phir-example-with-quantinuums-extended-openqasm-20
def test_spec_example() -> None:
"""From https://github.com/CQCL/phir/blob/main/spec.md .

Specifically "Overall PHIR Example with Quantinuum's Extended OpenQASM 2.0"
"""
with Path("tests/example.json").open() as f:
data = json.load(f) # type: ignore [misc]
data = json.load(f)

PHIRModel.model_validate(data)


def test_conditional_barrier() -> None:
"""Checks for barriers and qparallel blocks inside conditionals."""
with Path("tests/cond_barrier_qparallel.json").open() as f:
data = json.load(f)

PHIRModel.model_validate(data) # type: ignore [misc]
PHIRModel.model_validate(data)