Skip to content

Commit

Permalink
fix wasm issues (#1691)
Browse files Browse the repository at this point in the history
* fix wasm issues

* update changelog

* update tket version

* fix ci

* remove decompose_classical

* add testcase for appending two filled circuits

* add check for appending two wasm files with differen uid

* add test for different wasm uid

* add handling of circuit box

* fix ruff

* make wasm uid option in python

* make git_wasm_file_uid optional in c++

* Update tket/src/Circuit/macro_manipulation.cpp

Co-authored-by: Alec Edgington <[email protected]>

* Update pytket/binders/circuit/Circuit/main.cpp

Co-authored-by: Alec Edgington <[email protected]>

* Update pytket/binders/circuit/Circuit/main.cpp

Co-authored-by: Alec Edgington <[email protected]>

* fix changelog

* fix suggestion

* fix suggestion II

* fix suggestion III

---------

Co-authored-by: Alec Edgington <[email protected]>
  • Loading branch information
cqc-melf and cqc-alec authored Nov 26, 2024
1 parent ba0f7c0 commit a5f3169
Show file tree
Hide file tree
Showing 15 changed files with 505 additions and 14 deletions.
5 changes: 5 additions & 0 deletions pytket/binders/circuit/Circuit/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,11 @@ void def_circuit(py::class_<Circuit, std::shared_ptr<Circuit>> &pyCircuit) {
.def_property_readonly(
"n_gates", &Circuit::n_gates,
":return: the number of gates in the Circuit")
.def_property_readonly(
"wasm_uid",
[](const Circuit &circ) { return circ.get_wasm_file_uid(); },
":return: the unique WASM UID of the circuit, or `None` if the "
"circuit has none")
.def_property_readonly(
"n_qubits", &Circuit::n_qubits,
":return: the number of qubits in the circuit")
Expand Down
2 changes: 2 additions & 0 deletions pytket/binders/include/unit_downcast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ struct polymorphic_type_hook<tket::UnitID> {
// Node has no additional info but is more specific
// If Qubit is needed, then subtyping is sufficient
type = &typeid(tket::Node);
} else if (src->type() == tket::UnitType::WasmState) {
type = &typeid(tket::WasmState);
} else {
type = &typeid(tket::Bit);
}
Expand Down
42 changes: 41 additions & 1 deletion pytket/binders/unitid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ PYBIND11_MODULE(unit_id, m) {
m, "UnitType",
"Enum for data types of units in circuits (e.g. Qubits vs Bits).")
.value("qubit", UnitType::Qubit, "A single Qubit")
.value("wasmstate", UnitType::WasmState, "A single WasmState")
.value("bit", UnitType::Bit, "A single classical Bit");

py::class_<UnitID>(
Expand All @@ -114,7 +115,7 @@ PYBIND11_MODULE(unit_id, m) {
.def_property_readonly(
"type", &UnitID::type,
"Type of unit, either ``UnitType.qubit`` or "
"``UnitType.bit``");
"``UnitType.bit`` or ``UnitType.wasmstate``");

py::class_<Qubit, UnitID>(m, "Qubit", "A handle to a qubit")
.def("__copy__", [](const Qubit &id) { return Qubit(id); })
Expand Down Expand Up @@ -231,6 +232,45 @@ PYBIND11_MODULE(unit_id, m) {
"Construct Bit instance from JSON serializable "
"list representation of the Bit.");

py::class_<WasmState, UnitID>(m, "WasmState", "A handle to a wasmstate")
.def("__copy__", [](const WasmState &id) { return WasmState(id); })
.def(
"__deepcopy__",
[](const WasmState &id, const py::dict &) { return WasmState(id); })
.def(
py::init<unsigned>(),
"Constructs an id for some index in the default wasm "
"register\n\n:param index: The index in the register",
py::arg("index"))
.def("__eq__", &py_equals<WasmState>)
.def("__hash__", [](const WasmState &b) { return hash_value(b); })
.def(py::pickle(
[](const WasmState &b) {
return py::make_tuple(b.reg_name(), b.index());
},
[](const py::tuple &t) {
if (t.size() != 2)
throw std::runtime_error(
"Invalid state: tuple size: " + std::to_string(t.size()));
return WasmState(
t[0].cast<std::string>(), t[1].cast<std::vector<unsigned>>());
}))
.def(
"to_list",
[](const WasmState &b) {
return py::object(json(b)).cast<py::list>();
},
"Return a JSON serializable list representation of "
"the WasmState."
"\n\n:return: list containing register name and index")
.def_static(
"from_list",
[](const py::list &py_list) {
return json(py_list).get<WasmState>();
},
"Construct WasmState instance from JSON serializable "
"list representation of the WasmState.");

py::class_<Node, Qubit>(m, "Node", "A handle to a device node")
.def("__copy__", [](const Node &id) { return Node(id); })
.def(
Expand Down
2 changes: 1 addition & 1 deletion pytket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def requirements(self):
self.requires("pybind11_json/0.2.14")
self.requires("symengine/0.13.0")
self.requires("tkassert/0.3.4@tket/stable")
self.requires("tket/1.3.49@tket/stable")
self.requires("tket/1.3.50@tket/stable")
self.requires("tklog/0.3.3@tket/stable")
self.requires("tkrng/0.3.3@tket/stable")
self.requires("tktokenswap/0.3.9@tket/stable")
Expand Down
9 changes: 9 additions & 0 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ API changes:

* Remove the deprecated methods `auto_rebase_pass()` and `auto_squash_pass()`.

Features:

* Add `Circuit.wasm_uid` property to get the wasm UID from the circuit

Fixes:

* Fix `Circuit.append` for circuits containing wasm
* Fix issue with wrong parameters at `add_wasm`

1.35.0 (November 2024)
----------------------

Expand Down
5 changes: 5 additions & 0 deletions pytket/pytket/_tket/circuit.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2571,6 +2571,11 @@ class Circuit:
"""
A list of all qubit ids in the circuit
"""
@property
def wasm_uid(self) -> str | None:
"""
:return: the unique wasm uid of the circuit
"""
class ClBitVar:
"""
A bit variable within an expression
Expand Down
45 changes: 42 additions & 3 deletions pytket/pytket/_tket/unit_id.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ from typing import Any
from __future__ import annotations
import pytket.circuit.logic_exp
import typing
__all__ = ['Bit', 'BitRegister', 'Node', 'Qubit', 'QubitRegister', 'UnitID', 'UnitType']
__all__ = ['Bit', 'BitRegister', 'Node', 'Qubit', 'QubitRegister', 'UnitID', 'UnitType', 'WasmState']
class Bit(UnitID):
"""
A handle to a bit
Expand Down Expand Up @@ -397,7 +397,7 @@ class UnitID:
@property
def type(self) -> UnitType:
"""
Type of unit, either ``UnitType.qubit`` or ``UnitType.bit``
Type of unit, either ``UnitType.qubit`` or ``UnitType.bit`` or ``UnitType.wasmstate``
"""
class UnitType:
"""
Expand All @@ -407,11 +407,14 @@ class UnitType:
qubit : A single Qubit
wasmstate : A single WasmState
bit : A single classical Bit
"""
__members__: typing.ClassVar[dict[str, UnitType]] # value = {'qubit': <UnitType.qubit: 0>, 'bit': <UnitType.bit: 1>}
__members__: typing.ClassVar[dict[str, UnitType]] # value = {'qubit': <UnitType.qubit: 0>, 'wasmstate': <UnitType.wasmstate: 2>, 'bit': <UnitType.bit: 1>}
bit: typing.ClassVar[UnitType] # value = <UnitType.bit: 1>
qubit: typing.ClassVar[UnitType] # value = <UnitType.qubit: 0>
wasmstate: typing.ClassVar[UnitType] # value = <UnitType.wasmstate: 2>
@staticmethod
def _pybind11_conduit_v1_(*args, **kwargs): # type: ignore
...
Expand Down Expand Up @@ -441,6 +444,42 @@ class UnitType:
@property
def value(self) -> int:
...
class WasmState(UnitID):
"""
A handle to a wasmstate
"""
@staticmethod
def _pybind11_conduit_v1_(*args, **kwargs): # type: ignore
...
@staticmethod
def from_list(arg0: list) -> WasmState:
"""
Construct WasmState instance from JSON serializable list representation of the WasmState.
"""
def __copy__(self) -> WasmState:
...
def __deepcopy__(self, arg0: dict) -> WasmState:
...
def __eq__(self, arg0: typing.Any) -> bool:
...
def __getstate__(self) -> tuple:
...
def __hash__(self) -> int:
...
def __init__(self, index: int) -> None:
"""
Constructs an id for some index in the default wasm register
:param index: The index in the register
"""
def __setstate__(self, arg0: tuple) -> None:
...
def to_list(self) -> list:
"""
Return a JSON serializable list representation of the WasmState.
:return: list containing register name and index
"""
_DEBUG_ONE_REG_PREFIX: str = 'tk_DEBUG_ONE_REG'
_DEBUG_ZERO_REG_PREFIX: str = 'tk_DEBUG_ZERO_REG'
_TEMP_BIT_NAME: str = 'tk_SCRATCH_BIT'
Expand Down
6 changes: 1 addition & 5 deletions pytket/pytket/circuit/decompose_classical.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,11 +508,7 @@ def _decompose_expressions(circ: Circuit) -> tuple[Circuit, bool]:
newcirc.add_barrier(args)
else:
for arg in args:
if (
isinstance(arg, Bit)
and arg.reg_name != "_w" # workaround: this shouldn't be type Bit
and arg not in newcirc.bits
):
if isinstance(arg, Bit) and arg not in newcirc.bits:
newcirc.add_bit(arg)
newcirc.add_gate(op, args, **kwargs)
return newcirc, modified
Loading

0 comments on commit a5f3169

Please sign in to comment.