Skip to content

Commit

Permalink
Add spec (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
glorialeezero authored Nov 21, 2024
2 parents 7bacb03 + bce4cce commit 1109823
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"rich>=13"
"rich>=13",
"numpy>=2",
]

[project.optional-dependencies]
Expand Down
24 changes: 24 additions & 0 deletions qupsy/bin.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,26 @@
import argparse
from pathlib import Path

from qupsy.spec import parse_spec
from qupsy.utils import logger


def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--dry-run", action="store_true", help="Dry run")
parser.add_argument(
"specification", type=Path, metavar="SPEC", help="Specification file"
)

args = parser.parse_args()

logger.debug("Specification file: %s", args.specification)
spec = parse_spec(args.specification)

logger.info("Specification loaded: %s", args.specification)
logger.debug("Specification:\n%s", spec)

if args.dry_run:
return

print("Hello, qupsy!")
67 changes: 67 additions & 0 deletions qupsy/spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import json
from dataclasses import dataclass
from pathlib import Path
from typing import cast

import numpy as np
import numpy.typing as npt

from qupsy.language import CX, CRy, Gate, H, Ry, X
from qupsy.utils import logger

GATE_MAP: dict[str, type[Gate]] = {
"H": H,
"X": X,
"Ry": Ry,
"CX": CX,
"CRy": CRy,
}


@dataclass
class Spec:
gates: list[type[Gate]]
testcases: list[tuple[npt.ArrayLike, npt.ArrayLike]]

def __str__(self) -> str:
testcases_string: list[str] = []
for input, output in self.testcases:
input_str = str(input).splitlines()
input_str = input_str[0] + " ...]" if len(input_str) > 1 else input_str[0]
output_str = str(output).splitlines()
output_str = (
output_str[0] + " ...]" if len(output_str) > 1 else output_str[0]
)

testcases_string.append(
f" ( Input: {input_str},\n Output: {output_str}),"
)
return f"""Spec(
gates: [{", ".join(map(lambda g: g.__name__, self.gates))}],
testcases: [
{"\n".join(testcases_string)}
],
)"""


def parse_spec(spec: Path | str) -> Spec:
if isinstance(spec, str):
spec = Path(spec)
data = json.loads(spec.read_text())
gates = cast(list[str], data.get("gates", ["H", "X", "Ry", "CX", "CRy"]))
gates = [GATE_MAP[gate] for gate in gates]

testcases: list[tuple[npt.ArrayLike, npt.ArrayLike]] = []
for tc in data["testcases"].values():
output = np.fromstring(tc["output"], dtype="complex", sep=",")
input = (
tc["input"]
if "input" in tc
else (np.concat([[1], np.zeros_like(output[1:])]))
)
testcases.append((input, output))

logger.debug("Parsed output: %s", output)
logger.debug("Parsed input: %s", input)

return Spec(gates, testcases)

0 comments on commit 1109823

Please sign in to comment.