From ee8926bb5f3a6b43aea105f702c0e4ff3202b79b Mon Sep 17 00:00:00 2001 From: tatiana-s Date: Mon, 23 Dec 2024 12:23:00 +0000 Subject: [PATCH] feat!: Remove circuits from `py` expressions (#746) Closes #745 BREAKING CHANGE: `pytket` circuits no longer supported by `py` expressions (use `@pytket` or `load_pytket` instead) --- guppylang/checker/expr_checker.py | 27 -------- guppylang/compiler/expr_compiler.py | 18 +----- .../py_errors/load_tket2_not_installed.err | 11 ---- .../py_errors/load_tket2_not_installed.py | 21 ------- tests/error/py_errors/tket2_not_installed.err | 12 ++-- tests/error/py_errors/tket2_not_installed.py | 13 ++-- tests/error/test_py_errors.py | 9 --- tests/integration/test_py.py | 61 ------------------- 8 files changed, 15 insertions(+), 157 deletions(-) delete mode 100644 tests/error/py_errors/load_tket2_not_installed.err delete mode 100644 tests/error/py_errors/load_tket2_not_installed.py diff --git a/guppylang/checker/expr_checker.py b/guppylang/checker/expr_checker.py index 3f1dcc7f..9824e4c1 100644 --- a/guppylang/checker/expr_checker.py +++ b/guppylang/checker/expr_checker.py @@ -57,7 +57,6 @@ PyExprIncoherentListError, PyExprNotCPythonError, PyExprNotStaticError, - Tket2NotInstalled, ) from guppylang.checker.errors.type_errors import ( AttributeNotFoundError, @@ -135,7 +134,6 @@ TypeBase, function_tensor_signature, parse_function_tensor, - row_to_type, unify, ) @@ -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 diff --git a/guppylang/compiler/expr_compiler.py b/guppylang/compiler/expr_compiler.py index a28cec4c..524e7fd9 100644 --- a/guppylang/compiler/expr_compiler.py +++ b/guppylang/compiler/expr_compiler.py @@ -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 @@ -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 diff --git a/tests/error/py_errors/load_tket2_not_installed.err b/tests/error/py_errors/load_tket2_not_installed.err deleted file mode 100644 index 244f14c5..00000000 --- a/tests/error/py_errors/load_tket2_not_installed.err +++ /dev/null @@ -1,11 +0,0 @@ -Error: Tket2 not installed (at $FILE:14:0) - | -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` - -Guppy compilation failed due to 1 previous error diff --git a/tests/error/py_errors/load_tket2_not_installed.py b/tests/error/py_errors/load_tket2_not_installed.py deleted file mode 100644 index 5630ad4f..00000000 --- a/tests/error/py_errors/load_tket2_not_installed.py +++ /dev/null @@ -1,21 +0,0 @@ -from pytket import Circuit - -from guppylang.decorator import guppy -from guppylang.module import GuppyModule -from guppylang.std.quantum import qubit - -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) -> None: - guppy_circ(q) - - -module.compile() \ No newline at end of file diff --git a/tests/error/py_errors/tket2_not_installed.err b/tests/error/py_errors/tket2_not_installed.err index 18ebbe9a..244f14c5 100644 --- a/tests/error/py_errors/tket2_not_installed.err +++ b/tests/error/py_errors/tket2_not_installed.err @@ -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` diff --git a/tests/error/py_errors/tket2_not_installed.py b/tests/error/py_errors/tket2_not_installed.py index 5eafcf1e..5630ad4f 100644 --- a/tests/error/py_errors/tket2_not_installed.py +++ b/tests/error/py_errors/tket2_not_installed.py @@ -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() \ No newline at end of file diff --git a/tests/error/test_py_errors.py b/tests/error/test_py_errors.py index 1f3889a3..bdb6924c 100644 --- a/tests/error/test_py_errors.py +++ b/tests/error/test_py_errors.py @@ -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 @@ -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) diff --git a/tests/integration/test_py.py b/tests/integration/test_py.py index 95a4bd0f..3f353cec 100644 --- a/tests/integration/test_py.py +++ b/tests/integration/test_py.py @@ -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