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

[CQT-259] Integrate wait and barrier directives in cQASMv1 exporter #407

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
38ce5b7
Restore SGMQ notation for barrier links.
elenbaasc Dec 12, 2024
f4cbfde
Update CHANGELOG.md
elenbaasc Dec 13, 2024
2f6fb2a
Update opensquirrel/passes/exporter/cqasmv1_exporter.py
elenbaasc Dec 13, 2024
4cc918b
Update test/exporter/test_cqasmv1_exporter.py
elenbaasc Dec 13, 2024
30ff3b1
Resolve review comments.
elenbaasc Dec 13, 2024
70f8ab9
Update opensquirrel/passes/exporter/cqasmv1_exporter.py
elenbaasc Dec 16, 2024
7d95bad
Update test/exporter/test_cqasmv1_exporter.py
elenbaasc Dec 16, 2024
d864fcc
Update test/exporter/test_cqasmv1_exporter.py
elenbaasc Dec 16, 2024
43f3560
Update test/exporter/test_cqasmv1_exporter.py
elenbaasc Dec 16, 2024
c0c15ee
Merge develop into CQT-259
elenbaasc Jan 8, 2025
3e3c559
Revert changes to cQASMv1 exporter and comment barrier tests.
elenbaasc Jan 8, 2025
c226368
Implement barrier grouping as post-processing step
elenbaasc Jan 8, 2025
56827a9
Update opensquirrel/passes/exporter/cqasmv1_exporter.py
elenbaasc Jan 10, 2025
d4b7b28
Update opensquirrel/passes/exporter/cqasmv1_exporter.py
elenbaasc Jan 10, 2025
0c70f25
Fix regex module.
elenbaasc Jan 10, 2025
7976aab
Revert actions-poetry from v4 to v3 so the pipeline can run.
elenbaasc Jan 10, 2025
d0f8361
Update changelog to use the right wording.
elenbaasc Jan 10, 2025
9e9bec7
Update CHANGELOG.md
elenbaasc Jan 13, 2025
4989b3e
Update CHANGELOG.md
elenbaasc Jan 13, 2025
d9577fb
Update opensquirrel/passes/exporter/cqasmv1_exporter.py
elenbaasc Jan 14, 2025
580604b
Update opensquirrel/passes/exporter/cqasmv1_exporter.py
elenbaasc Jan 14, 2025
704d004
Fix formatting error.
elenbaasc Jan 14, 2025
043053a
Moved expection class to top of file.
elenbaasc Jan 15, 2025
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Change Log

All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).


## [ 0.2.0 ] - [ xxxx-yy-zz ]

### Added
- Restore SGMQ notation for barrier links in cQASMv1 Exporter (with tests).
39 changes: 22 additions & 17 deletions opensquirrel/passes/exporter/cqasmv1_exporter.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import annotations

from itertools import groupby
from typing import TYPE_CHECKING, SupportsFloat, SupportsInt

from opensquirrel.exceptions import UnsupportedGateError
from opensquirrel.ir import Barrier, Float, Gate, Init, Int, IRVisitor, Measure, Qubit, Reset, Wait
from opensquirrel.ir import Barrier, Float, Gate, Init, Int, IRVisitor, Measure, Qubit, Reset, Statement, Wait

if TYPE_CHECKING:
from opensquirrel.circuit import Circuit
Expand All @@ -14,12 +15,11 @@ class _CQASMv1Creator(IRVisitor):
# Precision used when writing out a float number
FLOAT_PRECISION = 8

def __init__(self, register_manager: RegisterManager) -> None:
def __init__(self, register_manager: RegisterManager, barrier_links: list[list[Statement]]) -> None:
self.register_manager = register_manager
qubit_register_size = self.register_manager.get_qubit_register_size()
self.cqasmv1_string = "version 1.0\n\n{}\n\n".format(
f"qubits {qubit_register_size}" if qubit_register_size > 0 else ""
)
self.output = "version 1.0\n\n{}\n\n".format(f"qubits {qubit_register_size}" if qubit_register_size > 0 else "")
self.barrier_links = barrier_links

def visit_qubit(self, qubit: Qubit) -> str:
qubit_register_name = self.register_manager.get_qubit_register_name()
Expand All @@ -35,24 +35,27 @@ def visit_float(self, f: SupportsFloat) -> str:

def visit_measure(self, measure: Measure) -> None:
qubit_argument = measure.arguments[0].accept(self) # type: ignore[index]
self.cqasmv1_string += f"{measure.name}_z {qubit_argument}\n"
self.output += f"{measure.name}_z {qubit_argument}\n"

def visit_init(self, init: Init) -> None:
qubit_argument = init.arguments[0].accept(self) # type: ignore[index]
self.cqasmv1_string += f"prep_z {qubit_argument}\n"
self.output += f"prep_z {qubit_argument}\n"

def visit_reset(self, reset: Reset) -> None:
qubit_argument = reset.arguments[0].accept(self) # type: ignore[index]
self.cqasmv1_string += f"prep_z {qubit_argument}\n"
self.output += f"prep_z {qubit_argument}\n"

def visit_barrier(self, barrier: Barrier) -> None:
qubit_argument = barrier.arguments[0].accept(self) # type: ignore[index]
self.cqasmv1_string += f"barrier {qubit_argument}\n"
if self.barrier_links and barrier == self.barrier_links[0][-1]:
qubit_register_name = self.register_manager.get_qubit_register_name()
qubit_indices = [str(barrier.arguments[0].index) for barrier in self.barrier_links[0]] # type: ignore
self.output += f"barrier {qubit_register_name}[{', '.join(qubit_indices)}]\n"
del self.barrier_links[0]

def visit_wait(self, wait: Wait) -> None:
qubit_argument = wait.arguments[0].accept(self) # type: ignore[index]
parameter = wait.arguments[1].accept(self) # type: ignore[index]
self.cqasmv1_string += f"wait {qubit_argument}, {parameter}\n"
self.output += f"wait {qubit_argument}, {parameter}\n"

def visit_gate(self, gate: Gate) -> None:
gate_name = gate.name.lower()
Expand All @@ -62,15 +65,17 @@ def visit_gate(self, gate: Gate) -> None:
if any(not isinstance(arg, Qubit) for arg in gate.arguments): # type: ignore[union-attr]
params = [arg.accept(self) for arg in gate.arguments if not isinstance(arg, Qubit)] # type: ignore[union-attr]
qubit_args = (arg.accept(self) for arg in gate.arguments if isinstance(arg, Qubit)) # type: ignore[union-attr]
self.cqasmv1_string += "{} {}{}\n".format(
gate_name, ", ".join(qubit_args), ", " + ", ".join(params) if params else ""
)
self.output += "{} {}{}\n".format(gate_name, ", ".join(qubit_args), ", " + ", ".join(params) if params else "")


def export(circuit: Circuit) -> str:
cqasmv1_creator = _CQASMv1Creator(circuit.register_manager)

barrier_links = [
list(barrier_link)
for barrier, barrier_link in groupby(circuit.ir.statements, lambda stmt: isinstance(stmt, Barrier))
if barrier
]
cqasmv1_creator = _CQASMv1Creator(circuit.register_manager, barrier_links)
circuit.ir.accept(cqasmv1_creator)

# Remove all trailing lines and leave only one
return cqasmv1_creator.cqasmv1_string.rstrip() + "\n"
return cqasmv1_creator.output.rstrip() + "\n"
54 changes: 54 additions & 0 deletions test/exporter/test_cqasmv1_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,57 @@ def test_anonymous_gates(gate: Gate) -> None:
with pytest.raises(UnsupportedGateError, match="not supported"): # noqa: PT012
qc = builder.to_circuit()
qc.export(fmt=ExportFormat.CQASM_V1)


@pytest.mark.parametrize(
("v3_input", "v3_output", "v1_output"),
[
(
"version 3.0; qubit[1] q; barrier q[0]",
"version 3.0\n\nqubit[1] q\n\nbarrier q[0]\n",
"version 1.0\n\nqubits 1\n\nbarrier q[0]\n",
),
(
"version 3.0; qubit[3] q; barrier q[0:2]",
"version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\n",
"version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n",
),
(
"version 3.0; qubit[1] q; barrier q[0, 0]",
"version 3.0\n\nqubit[1] q\n\nbarrier q[0]\nbarrier q[0]\n",
"version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n",
),
(
"version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]",
"version 3.0\n\nqubit[6] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\nbarrier q[5]\nbarrier q[3]\n"
"barrier q[4]\nbarrier q[1]\n",
"version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n",
),
(
"version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3];"
"barrier q[0]",
"version 3.0\n\nqubit[5] q\n\nbarrier q[0]\nH q[1]\nbarrier q[1]\nbarrier q[2]\nX q[2]\n"
"barrier q[3]\nbarrier q[4]\nbarrier q[1]\nY q[3]\nbarrier q[0]\n",
"version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3]\n"
"barrier q[0]\n",
),
(
"version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]",
"version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nX q[2]\nbarrier q[1]\n",
"version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\n",
),
],
ids=[
"no_link",
"single_link",
"repeated_index",
"preserve_order",
"with_instructions",
"link_consecutive_barriers",
],
)
def test_barrier_links(v3_input: str, v3_output: str, v1_output: str) -> None:
qc = Circuit.from_string(v3_input)
assert str(qc) == v3_output
cqasm_v1_string = qc.export(fmt=ExportFormat.CQASM_V1)
assert cqasm_v1_string == v1_output
Loading