Skip to content
Open
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
run: uv python install ${{ env.PYTHON_LOWEST }}
- name: Setup dependencies
# avoid building qis-compiler
run: uv sync --package=tket --exact --python ${{ env.PYTHON_LOWEST }}
run: uv sync --package=tket --exact --all-extras --python ${{ env.PYTHON_LOWEST }}
- name: Type check with mypy
run: uv run mypy .
- name: Check formatting with ruff
Expand Down Expand Up @@ -297,7 +297,7 @@ jobs:
run: uv python install ${{ env.PYTHON_LOWEST }}
- name: Setup dependencies
# avoid building qis-compiler
run: uv sync --package=tket --exact --python ${{ env.PYTHON_LOWEST }}
run: uv sync --package=tket --exact --all-extras --python ${{ env.PYTHON_LOWEST }}
- name: Run python tests with coverage instrumentation
run: uv run --no-project pytest --cov=./ --cov-report=xml ${{ env.PKGS }}
- name: Upload python coverage to codecov.io
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
RES: ${{ matrix.target.resolution }}
run: |
UV_RESOLUTION="$RES" uv lock --no-sources -U
UV_RESOLUTION="$RES" uv sync --no-sources --no-install-workspace
UV_RESOLUTION="$RES" uv sync --all-extras --no-sources --no-install-workspace
uv pip install --no-sources tket-exts
uv pip install --no-sources tket-eccs
uv run --no-sync maturin develop
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ repos:
- id: mypy-check
name: mypy
description: Check python code with `mypy`.
entry: uv run mypy .
entry: uv run --all-extras mypy .
language: system
files: \.py$
pass_filenames: false
Expand Down
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ _check_default_conan_profile:
# setting up the pre-commit hooks.
setup: && _check_default_conan_profile _check_nextest_installed
uv tool install conan
uv sync
uv sync --all-extras
[[ -n "${TKET_JUST_INHIBIT_GIT_HOOKS:-}" ]] || uv run pre-commit install -t pre-commit

# Run the pre-commit checks.
Expand Down
6 changes: 2 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ dev = [
"pip >=25",
# Pyyaml 0.6.0 makes setuptools fail. This ensures we're using a newer version.
"pyyaml >=6.0.2",
"hugr>=0.16"
]
conan = [
"conan >= 2.23.0,<3",
"hugr>=0.16",
]
conan = ["conan >= 2.23.0,<3"]

[tool.uv]
prerelease = "explicit"
Expand Down
1 change: 1 addition & 0 deletions qis-compiler/python/tests/generate_hugrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# dependencies = [
# "guppylang ==0.21.9",
# "tket",
# "pytket >=2.1.0,<3",
# ]
# ///

Expand Down
5 changes: 4 additions & 1 deletion tket-py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ classifiers = [

dependencies = [
'hugr ~= 0.16.0',
"pytket>=2.1.0,<3",
'tket_eccs ~= 0.5.1',
'tket_exts >= 0.12.3, <0.13',
]

[project.optional-dependencies]
# The pytket python library is only used for type checking.
pytket = ["pytket>=2.1.0,<3"]

[tool.uv.sources]
tket_eccs = { workspace = true }
tket_exts = { workspace = true }
Expand Down
28 changes: 18 additions & 10 deletions tket-py/test/test_circuit.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from dataclasses import dataclass
import pytest

from pytket._tket.circuit import Circuit
from dataclasses import dataclass

from tket._state import (
CompilationState,
Expand All @@ -20,7 +20,11 @@ def __add__(self, other):


def test_cost():
circ = CompilationState.from_tket1(Circuit(4).CX(0, 1).H(1).CX(1, 2).CX(0, 3).H(0))
pytket = pytest.importorskip("pytket")

circ = CompilationState.from_tket1(
pytket.Circuit(4).CX(0, 1).H(1).CX(1, 2).CX(0, 3).H(0)
)

print(circ.circuit_cost(lambda op: int(op == TketOp.CX)))

Expand All @@ -31,16 +35,19 @@ def test_cost():


def test_hash():
circA = CompilationState.from_tket1(Circuit(4).CX(0, 1).CX(1, 2).CX(0, 3))
circB = CompilationState.from_tket1(Circuit(4).CX(1, 2).CX(0, 1).CX(0, 3))
circC = CompilationState.from_tket1(Circuit(4).CX(0, 1).CX(0, 3).CX(1, 2))
pytket = pytest.importorskip("pytket")

circA = CompilationState.from_tket1(pytket.Circuit(4).CX(0, 1).CX(1, 2).CX(0, 3))
circB = CompilationState.from_tket1(pytket.Circuit(4).CX(1, 2).CX(0, 1).CX(0, 3))
circC = CompilationState.from_tket1(pytket.Circuit(4).CX(0, 1).CX(0, 3).CX(1, 2))

assert hash(circA) != hash(circB)
assert hash(circA) == hash(circC)


def test_conversion():
tk1 = Circuit(4).CX(0, 2).CX(1, 2).CX(1, 3)
pytket = pytest.importorskip("pytket")
tk1 = pytket.Circuit(4).CX(0, 2).CX(1, 2).CX(1, 3)

tk2 = CompilationState.from_tket1(tk1)
mermaid = tk2.render_mermaid()
Expand All @@ -51,11 +58,12 @@ def test_conversion():
tk1_back = tk2.to_tket1()

assert tk1_back == tk1
assert type(tk1_back) is Circuit
assert type(tk1_back) is pytket.Circuit


def test_conversion_qsystem():
tk1 = Circuit(2).ZZPhase(0.75, 0, 1).PhasedX(0.25, 0.33, 1)
pytket = pytest.importorskip("pytket")
tk1 = pytket.Circuit(2).ZZPhase(0.75, 0, 1).PhasedX(0.25, 0.33, 1)

tk2 = CompilationState.from_tket1(tk1)
mermaid = tk2.render_mermaid()
Expand All @@ -71,4 +79,4 @@ def test_conversion_qsystem():
tk1_back = tk2.to_tket1()

assert tk1_back == tk1
assert type(tk1_back) is Circuit
assert type(tk1_back) is pytket.Circuit
15 changes: 10 additions & 5 deletions tket-py/test/test_optimiser.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
from pytket import Circuit
import pytest

from tket._state import CompilationState
from tket._rewrite import ECCRewriter
from tket._optimiser import BadgerOptimiser


def test_simple_optimiser():
"""a simple circuit matching test"""
tk = CompilationState.from_tket1(Circuit(3).CX(0, 1).CX(0, 1).CX(1, 2))
pytket = pytest.importorskip("pytket")
tk = CompilationState.from_tket1(pytket.Circuit(3).CX(0, 1).CX(0, 1).CX(1, 2))
opt = BadgerOptimiser.compile_eccs("test_files/eccs/cx_cx_eccs.json")

opt.optimise(tk._inner, max_circuit_count=3)
cc = tk.to_tket1()
exp_c = Circuit(3).CX(1, 2)
exp_c = pytket.Circuit(3).CX(1, 2)

assert cc == exp_c


def test_compose_rewriter():
"""test composing rewriters."""
tk = CompilationState.from_tket1(Circuit(3).CX(0, 1).CX(0, 1).H(0).H(0).CX(0, 2))
pytket = pytest.importorskip("pytket")
tk = CompilationState.from_tket1(
pytket.Circuit(3).CX(0, 1).CX(0, 1).H(0).H(0).CX(0, 2)
)
cx_rewriter = ECCRewriter.compile_eccs("test_files/eccs/cx_cx_eccs.json")
h_rewriter = ECCRewriter.compile_eccs("test_files/eccs/h_h_eccs.json")

opt = BadgerOptimiser([cx_rewriter, h_rewriter])
opt.optimise(tk._inner, max_circuit_count=3)
cc = tk.to_tket1()
exp_c = Circuit(3).CX(0, 2)
exp_c = pytket.Circuit(3).CX(0, 2)

assert cc == exp_c
8 changes: 4 additions & 4 deletions tket-py/test/test_pass.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from pytket import Circuit, OpType
from typing import Callable, Any
from tket._ops import TketOp
from tket.passes import (
Expand All @@ -16,14 +15,15 @@
from hypothesis import given, settings

from tket.passes import PytketHugrPass
from pytket.passes import CliffordSimp, SquashRzPhasedX, SequencePass
from hugr.build.base import Hugr

import pytest


from pathlib import Path

pytket = pytest.importorskip("pytket")
from pytket import Circuit, OpType # noqa: E402
from pytket.passes import CliffordSimp, SquashRzPhasedX, SequencePass # noqa: E402


normalize = NormalizeGuppy()

Expand Down
17 changes: 10 additions & 7 deletions tket-py/test/test_pauli_prop.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import itertools

import pytest
from pytket._tket.circuit import Circuit

from hugr.ops import Custom
from hugr.hugr import Wire
Expand Down Expand Up @@ -160,6 +159,8 @@ def map_op(op: Custom) -> str:

@pytest.mark.skip(reason="Broken with hugr 0.8.0. See comment in `propagate_matcher`.")
def test_simple_z_prop(propagate_matcher: RuleMatcher):
pytket = pytest.importorskip("pytket")

c = CircBuild.with_nqb(2)

(h_node_e, *_) = c.extend(H(0), H(0), CX(0, 1))
Expand All @@ -169,17 +170,19 @@ def test_simple_z_prop(propagate_matcher: RuleMatcher):

add_error_after(t2c, h_node_e[0], PauliX)

assert t2c.to_tket1() == Circuit(2).H(0).X(0).H(0).CX(0, 1)
assert t2c.to_tket1() == pytket.Circuit(2).H(0).X(0).H(0).CX(0, 1)

assert apply_exhaustive(t2c, propagate_matcher) == 2

assert t2c.to_tket1() == Circuit(2).H(0).H(0).CX(0, 1).Z(0)
assert t2c.to_tket1() == pytket.Circuit(2).H(0).H(0).CX(0, 1).Z(0)

assert final_pauli_string(t2c) == "ZI"


@pytest.mark.skip(reason="Broken with hugr 0.8.0. See comment in `propagate_matcher`.")
def test_cat(propagate_matcher: RuleMatcher):
pytket = pytest.importorskip("pytket")

c = CircBuild.with_nqb(4)
(h_node, *_) = c.extend(
H(2),
Expand All @@ -191,13 +194,13 @@ def test_cat(propagate_matcher: RuleMatcher):
t2c = c.finish()

add_error_after(t2c, h_node[0], PauliX)
assert t2c.to_tket1() == Circuit(4).H(2).X(2).CX(2, 1).CX(2, 3).CX(1, 0)
assert t2c.to_tket1() == pytket.Circuit(4).H(2).X(2).CX(2, 1).CX(2, 3).CX(1, 0)

assert apply_exhaustive(t2c, propagate_matcher) == 3

assert t2c.to_tket1() == Circuit(4).H(2).CX(2, 1).CX(2, 3).CX(1, 0).X(0).X(1).X(
2
).X(3)
assert t2c.to_tket1() == pytket.Circuit(4).H(2).CX(2, 1).CX(2, 3).CX(1, 0).X(0).X(
1
).X(2).X(3)

assert final_pauli_string(t2c) == "XXXX"

Expand Down
7 changes: 5 additions & 2 deletions tket-py/test/test_portmatching.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from pytket import Circuit
from pytket.qasm import circuit_from_qasm_str
import pytest
from tket._pattern import CircuitPattern, PatternMatcher
from tket._state import CompilationState

pytket = pytest.importorskip("pytket")
from pytket import Circuit # noqa: E402
from pytket.qasm import circuit_from_qasm_str # noqa: E402


def _tk(circ: Circuit):
"""Convert a pytket Circuit to a Rust CompilationState."""
Expand Down
12 changes: 8 additions & 4 deletions tket-py/test/test_scopes.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
from .test_pass import _hugr_from_path, _count_ops
import pytest

from .test_pass import _hugr_from_path, _count_ops

from pytket.passes import FullPeepholeOptimise
from tket.passes import NormalizeGuppy, PytketHugrPass
from hugr.passes.scope import GlobalScope, LocalScope

normalize = NormalizeGuppy()


def test_nested_function_opt_global() -> None:
pytket = pytest.importorskip("pytket")

h = _hugr_from_path("test_files/guppy_optimization/nested/nested.flat.hugr")
h_normalized = normalize(h)

fpo = PytketHugrPass(FullPeepholeOptimise())
fpo = PytketHugrPass(pytket.passes.FullPeepholeOptimise())
fpo_preserve_entrypoint = fpo.with_scope(GlobalScope.PRESERVE_ENTRYPOINT)

opt_hugr = fpo_preserve_entrypoint(h_normalized)
Expand All @@ -22,10 +24,12 @@ def test_nested_function_opt_global() -> None:


def test_nested_function_opt_local() -> None:
pytket = pytest.importorskip("pytket")

h = _hugr_from_path("test_files/guppy_optimization/nested/nested.flat.hugr")
h_normalized = normalize(h)

fpo = PytketHugrPass(FullPeepholeOptimise())
fpo = PytketHugrPass(pytket.passes.FullPeepholeOptimise())
fpo_local_flat = fpo.with_scope(LocalScope.FLAT)

flat_opt_hugr = fpo_local_flat(h_normalized)
Expand Down
7 changes: 6 additions & 1 deletion tket-py/tket/_tket/state.pyi
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from typing import Any, Callable
from pytket._tket.circuit import Circuit as Tk1Circuit

from tket._tket.ops import TketOp
from hugr.envelope import EnvelopeConfig

try:
from pytket._tket.circuit import Circuit as Tk1Circuit
except ImportError:
# Pytket is only available as an optional dependency under the `pytket` extra.
from typing import Any as Tk1Circuit # type: ignore

class CompilationState:
"""Program state definition.

Expand Down
11 changes: 8 additions & 3 deletions tket-py/tket/passes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
from pathlib import Path
import json
from dataclasses import dataclass
from typing import TYPE_CHECKING

from hugr import Hugr
from pytket.passes import (
BasePass,
)

from tket import _state
from ._tket import passes as _passes, optimiser as _optimiser
Expand All @@ -20,6 +18,13 @@
)
from hugr.passes.scope import PassScope, GlobalScope

if TYPE_CHECKING:
try:
# Available via the `pytket` extra, and as a dev dependency for testing.
from pytket.passes import BasePass
except ImportError:
from typing import Any as BasePass # type: ignore


__all__ = ["PytketHugrPass", "PassResult", "NormalizeGuppy", "ModifierResolverPass"]

Expand Down
9 changes: 7 additions & 2 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading