Skip to content

Commit

Permalink
Merge branch 'main' into fix/pre-commit-config
Browse files Browse the repository at this point in the history
  • Loading branch information
qartik authored Jan 22, 2024
2 parents 784d8af + 45c2bf0 commit cd0f5ea
Show file tree
Hide file tree
Showing 17 changed files with 197 additions and 196 deletions.
38 changes: 11 additions & 27 deletions .github/workflows/pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ name: Pull Request

on: pull_request

env:
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache"

jobs:
check:
name: Check Python
Expand All @@ -13,6 +17,8 @@ jobs:

steps:
- uses: actions/checkout@v3
- name: Run sccache-cache
uses: mozilla-actions/[email protected]
- name: Install poetry
run: pipx install poetry
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -21,20 +27,9 @@ jobs:
python-version: ${{ matrix.python-version }}
cache: "poetry"

- name: Build Hugr validator
uses: PyO3/maturin-action@v1
with:
command: build
sccache: 'true'
rust-toolchain: '1.75'
working-directory: validator

- name: Install Guppy
run: poetry install

- name: Install Hugr validator
run: poetry add validator/target/wheels/*

- name: Type check with mypy
run: poetry run mypy guppylang

Expand All @@ -50,25 +45,14 @@ jobs:
src: "./guppylang"
args: check

- name: Install Guppy with validation
run: poetry install --with validation

- name: Run tests
run: poetry run pytest

- name: Checkout tket2
uses: actions/checkout@v4
with:
repository: CQCL/tket2
path: tket2

- name: Build tket2-py
uses: PyO3/maturin-action@v1
with:
command: build
sccache: 'true'
rust-toolchain: '1.75'
working-directory: tket2/tket2-py

- name: Install tket2-py validator
run: poetry add tket2/target/wheels/*
- name: Install tket2 dependencies
run: poetry install --with pytket

- name: Rerun `py(...)` expression tests with tket2 installed
run: poetry run pytest tests/integration/test_py.py tests/error/test_py_errors.py
96 changes: 66 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,70 @@
# Guppy

## About
Guppy is a quantum programming language that is fully embedded into Python.
It allows you to write high-level hybrid quantum programs with classical control flow and mid-circuit measurements using Pythonic syntax:

```python
from guppylang import guppy, Qubit, quantum

guppy.load(quantum)

# Teleports the state in `src` to `tgt`.
@guppy
def teleport(src: Qubit, tgt: Qubit) -> Qubit:
# Create ancilla and entangle it with src and tgt
tmp = Qubit()
tmp, tgt = cx(h(tmp), tgt)
src, tmp = cx(src, tmp)

# Apply classical corrections
if measure(h(src)):
tgt = z(tgt)
if measure(tmp):
tgt = x(tgt)
return tgt
```

More examples and tutorials are available [here][examples].

[examples]: ./examples/


## Install

Guppy can be installed via `pip`. Requires Python >= 3.10.

```sh
pip install guppylang
```


## Usage

See the [Getting Started][getting-started] guide and the other [examples].

[getting-started]: ./examples/1-Getting-Started.md

TODO

## Getting Started
## Development

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.

### Prerequisites

- Python >=3.10
- Python >= 3.10
- [Poetry](https://python-poetry.org/docs/#installation)
- [Rust](https://www.rust-lang.org/tools/install) >= 1.75.0 (only needed for tests)

### Installing


First make sure poetry [is
installed](https://python-poetry.org/docs/#installation).

Then run the following to setup your virtual environment and install dependencies:
Run the following to setup your virtual environment and install dependencies:

```sh
poetry install
poetry install --with validation
```

Note that the `--with validation` flag is optional and only needed to run integration tests.

You can then activate the virtual environment and work within it with:

```sh
Expand All @@ -35,50 +76,45 @@ automate this when entering and leaving a directory.

To run a single command in the shell, just prefix it with `poetry run`.

### Pre-commit

### Git blame

You can configure Git to ignore formatting commits when using `git blame` by running
Install the pre-commit hook by running:

```sh
git config blame.ignoreRevsFile .git-blame-ignore-revs
poetry run pre-commit install
```

## Usage

TODO

## Testing
### Testing

First, build the PyO3 Hugr validation library from the `validator` directory using
Run tests using

```sh
maturin develop
poetry run pytest -v
```

Run tests using
You have to install extra dependencies to test automatic circuit conversion from `pytket`:

```sh
poetry run pytest -v
poetry install --with pytket
poetry run pytest -v # Now rerun tests
```


Integration test cases can be exported to a directory using

```sh
poetry run pytest --export-test-cases=guppy-exports

```

which will create a directory `./guppy-exports` populated with hugr modules serialised in msgpack.
which will create a directory `./guppy-exports` populated with hugr modules serialised in JSON.

## Packaging
### Experimental: Execution

```sh
poetry build
```
See the [guppy-runner](https://github.com/CQCL/guppy-runner) repository for in-progress work for compiling Guppy source programs and executing them.

## License

This project is licensed under Apache License, Version 2.0 ([LICENSE][] or http://www.apache.org/licenses/LICENSE-2.0).
This project is licensed under Apache License, Version 2.0 ([LICENCE][] or http://www.apache.org/licenses/LICENSE-2.0).

[LICENSE]: ./LICENSE
[LICENCE]: ./LICENCE
17 changes: 16 additions & 1 deletion devenv.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
{ ... }:
{ pkgs, lib, ... }:

{
# for building optional tket2 dependency
# see https://github.com/CQCL/tket2/blob/main/devenv.nix
packages = [
pkgs.just
]
++ lib.optionals pkgs.stdenv.isLinux [
pkgs.stdenv.cc.cc.lib
]
++ lib.optionals pkgs.stdenv.isDarwin (
with pkgs.darwin.apple_sdk; [
frameworks.CoreServices
frameworks.CoreFoundation
]
);

languages.python = {
enable = true;
poetry = {
Expand Down
7 changes: 7 additions & 0 deletions examples/1-Getting-Started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

# 1. Getting Started

This file explains how you can get started using Guppy.

TODO

6 changes: 5 additions & 1 deletion guppylang/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
__all__ = ["types.py"]
from guppylang.decorator import guppy
from guppylang.module import GuppyModule
from guppylang.prelude import builtins, quantum
from guppylang.prelude.builtins import Bool, Float, Int, List, linst
from guppylang.prelude.quantum import Qubit
7 changes: 7 additions & 0 deletions guppylang/decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,13 @@ def dummy(*args: Any, **kwargs: Any) -> Any:

return dec

def load(self, m: ModuleType | GuppyModule) -> None:
caller = self._get_python_caller()
if caller not in self._modules:
self._modules[caller] = GuppyModule(caller.name)
module = self._modules[caller]
module.load(m)

def take_module(self, id: ModuleIdentifier | None = None) -> GuppyModule:
"""Returns the local GuppyModule, removing it from the local state."""
orig_id = id
Expand Down
6 changes: 1 addition & 5 deletions guppylang/hugr/hugr.py
Original file line number Diff line number Diff line change
Expand Up @@ -794,10 +794,6 @@ def to_raw(self) -> raw.RawHugr:
raise ValueError("Raw Hugr requires a root node")
return raw.RawHugr(nodes=nodes, edges=edges)

def serialize(self) -> bytes:
"""Serialize this Hugr in binary format."""
return self.to_raw().packb()

def serialize_json(self) -> str:
def serialize(self) -> str:
"""Serialize this Hugr in JSON format."""
return self.to_raw().to_json()
9 changes: 0 additions & 9 deletions guppylang/hugr/raw.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from typing import Any, Literal

import ormsgpack
from pydantic import BaseModel

from guppylang.hugr.ops import NodeID, OpType
Expand All @@ -14,18 +13,10 @@ class RawHugr(BaseModel):
nodes: list[OpType]
edges: list[Edge]

def packb(self) -> bytes:
return ormsgpack.packb(self.model_dump(), option=ormsgpack.OPT_NON_STR_KEYS)

def to_json(self) -> str:
"""Return a JSON representation of the Hugr."""
return self.model_dump_json()

@classmethod
def unpackb(cls, b: bytes) -> "RawHugr":
"""Decode a msgpack-encoded Hugr."""
return cls(**ormsgpack.unpackb(b, option=ormsgpack.OPT_NON_STR_KEYS))

@classmethod
def load_json(cls, json: dict[Any, Any]) -> "RawHugr":
"""Decode a JSON-encoded Hugr."""
Expand Down
Loading

0 comments on commit cd0f5ea

Please sign in to comment.