Skip to content

Commit

Permalink
feat!: Remove circuits from py expressions (#746)
Browse files Browse the repository at this point in the history
Closes #745 

BREAKING CHANGE: `pytket` circuits no longer supported by `py`
expressions (use `@pytket` or `load_pytket` instead)
  • Loading branch information
tatiana-s authored Dec 23, 2024
1 parent aa9341b commit ee8926b
Show file tree
Hide file tree
Showing 8 changed files with 15 additions and 157 deletions.
27 changes: 0 additions & 27 deletions guppylang/checker/expr_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
PyExprIncoherentListError,
PyExprNotCPythonError,
PyExprNotStaticError,
Tket2NotInstalled,
)
from guppylang.checker.errors.type_errors import (
AttributeNotFoundError,
Expand Down Expand Up @@ -135,7 +134,6 @@
TypeBase,
function_tensor_signature,
parse_function_tensor,
row_to_type,
unify,
)

Expand Down Expand Up @@ -1206,31 +1204,6 @@ def python_value_to_guppy_type(
case list():
return _python_list_to_guppy_type(v, node, globals, type_hint)
case _:
# Pytket conversion is an experimental feature
# if pytket and tket2 are installed
try:
import pytket

if isinstance(v, pytket.circuit.Circuit):
# We also need tket2 installed
try:
import tket2 # type: ignore[import-untyped, import-not-found, unused-ignore] # noqa: F401

qubit = cast(TypeDef, globals["qubit"]).check_instantiate(
[], globals
)
return FunctionType(
[FuncInput(qubit, InputFlags.Inout)] * v.n_qubits,
row_to_type([bool_type()] * v.n_bits),
)
except ImportError:
err = Tket2NotInstalled(node)
err.add_sub_diagnostic(
Tket2NotInstalled.InstallInstruction(None)
)
raise GuppyError(err) from None
except ImportError:
pass
return None


Expand Down
18 changes: 2 additions & 16 deletions guppylang/compiler/expr_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import hugr.std.int
import hugr.std.logic
import hugr.std.prelude
from hugr import Hugr, Wire, ops
from hugr import Wire, ops
from hugr import tys as ht
from hugr import val as hv
from hugr.build.cond_loop import Conditional
Expand Down Expand Up @@ -620,21 +620,7 @@ def python_value_to_hugr(v: Any, exp_ty: Type) -> hv.Value | None:
opt_vs: list[hv.Value] = [hv.Some(v) for v in vs]
return hugr.std.collections.array.ArrayVal(opt_vs, opt_ty)
case _:
# TODO replace with hugr protocol handling: https://github.com/CQCL/guppylang/issues/563
# Pytket conversion is an experimental feature
# if pytket and tket2 are installed
try:
import pytket

if isinstance(v, pytket.circuit.Circuit):
from tket2.circuit import ( # type: ignore[import-untyped, import-not-found, unused-ignore]
Tk2Circuit,
)

circ = Hugr.load_json(Tk2Circuit(v).to_hugr_json()) # type: ignore[attr-defined, unused-ignore]
return hv.Function(circ)
except ImportError:
pass
return None
return None


Expand Down
11 changes: 0 additions & 11 deletions tests/error/py_errors/load_tket2_not_installed.err

This file was deleted.

21 changes: 0 additions & 21 deletions tests/error/py_errors/load_tket2_not_installed.py

This file was deleted.

12 changes: 6 additions & 6 deletions tests/error/py_errors/tket2_not_installed.err
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
Error: Tket2 not installed (at $FILE:16:8)
Error: Tket2 not installed (at $FILE:14:0)
|
14 | @guppy(module)
15 | def foo(q: qubit) -> qubit:
16 | f = py(circ)
| ^^^^^^^^ Experimental pytket compatibility requires `tket2` to be
| installed
12 | module.load(qubit)
13 |
14 | guppy.load_pytket("guppy_circ", circ, module)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Experimental pytket compatibility requires `tket2` to be
| installed

Help: Install tket2: `pip install tket2`

Expand Down
13 changes: 7 additions & 6 deletions tests/error/py_errors/tket2_not_installed.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@
from guppylang.module import GuppyModule
from guppylang.std.quantum import qubit

circ = Circuit(1)
circ.H(0)
circ = Circuit(2)
circ.X(0)
circ.Y(1)

module = GuppyModule("test")
module.load(qubit)

guppy.load_pytket("guppy_circ", circ, module)

@guppy(module)
def foo(q: qubit) -> qubit:
f = py(circ)
return f(q)
def foo(q: qubit) -> None:
guppy_circ(q)


module.compile()
module.compile()
9 changes: 0 additions & 9 deletions tests/error/test_py_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
if x.is_file()
and x.suffix == ".py"
and x.name not in ("__init__.py", "tket2_not_installed.py")
and x.name not in ("__init__.py", "load_tket2_not_installed.py")
]

# Turn paths into strings, otherwise pytest doesn't display the names
Expand All @@ -35,11 +34,3 @@ def test_tket2_not_installed(capsys, snapshot):
pathlib.Path(__file__).parent.resolve() / "py_errors" / "tket2_not_installed.py"
)
run_error_test(str(path), capsys, snapshot)


@pytest.mark.skipif(tket2_installed, reason="tket2 is installed")
def test_load_tket2_not_installed(capsys, snapshot):
path = (
pathlib.Path(__file__).parent.resolve() / "py_errors" / "load_tket2_not_installed.py"
)
run_error_test(str(path), capsys, snapshot)
61 changes: 0 additions & 61 deletions tests/integration/test_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,67 +125,6 @@ def foo() -> None:
validate(foo)


@pytest.mark.skipif(not tket2_installed, reason="Tket2 is not installed")
@pytest.mark.skip("Fails because of extensions in types #343")
def test_pytket_single_qubit(validate):
from pytket import Circuit

circ = Circuit(1)
circ.H(0)

module = GuppyModule("test")
module.load_all(quantum)

@guppy(module)
def foo(q: qubit) -> qubit:
f = py(circ)
return f(q)

validate(module.compile())


@pytest.mark.skipif(not tket2_installed, reason="Tket2 is not installed")
@pytest.mark.skip("Fails because of extensions in types #343")
def test_pytket_multi_qubit(validate):
from pytket import Circuit

circ = Circuit(3)
circ.CX(0, 1)
circ.H(2)
circ.T(0)
circ.CZ(2, 0)

module = GuppyModule("test")
module.load_all(quantum)

@guppy(module)
def foo(q1: qubit, q2: qubit, q3: qubit) -> tuple[qubit, qubit, qubit]:
return py(circ)(q1, q2, q3)

validate(module.compile())


@pytest.mark.skip(
"Now requires a conversion pass to turn TKET1 measurements into TKET2 measurements"
)
@pytest.mark.skipif(not tket2_installed, reason="Tket2 is not installed")
def test_pytket_measure(validate):
from pytket import Circuit

circ = Circuit(1)
circ.H(0)
circ.measure_all()

module = GuppyModule("test")
module.load_all(quantum)

@guppy(module)
def foo(q: qubit) -> tuple[qubit, bool]:
return py(circ)(q)

validate(module.compile())


def test_func_type_arg(validate):
module = GuppyModule("test")
n = 10
Expand Down

0 comments on commit ee8926b

Please sign in to comment.