Coverage for /home/runner/work/tket/tket/pytket/pytket/circuit/__init__.py: 96%
76 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-10 11:51 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-10 11:51 +0000
1# Copyright Quantinuum
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
15"""The circuit module provides an API to interact with the
16tket :py:class:`~.Circuit` data structure.
17This module is provided in binary form during the PyPI installation."""
19from collections.abc import Callable, Sequence
20from typing import (
21 Any,
22 Optional,
23 Union,
24)
26from pytket import wasm
27from pytket._tket.circuit import *
28from pytket._tket.circuit import Circuit
29from pytket._tket.pauli import Pauli
30from pytket._tket.unit_id import *
32# prefixes for assertion bits
33from pytket._tket.unit_id import (
34 _DEBUG_ONE_REG_PREFIX,
35 _DEBUG_ZERO_REG_PREFIX,
36 Bit,
37 BitRegister,
38)
40from .clexpr import wired_clexpr_from_logic_exp
41from .logic_exp import (
42 BinaryOp,
43 LogicExp,
44 Ops,
45 if_bit,
46 if_not_bit,
47 reg_eq,
48 reg_geq,
49 reg_gt,
50 reg_leq,
51 reg_lt,
52 reg_neq,
53)
56def add_wasm( # noqa: PLR0913
57 self: Circuit,
58 funcname: str,
59 filehandler: wasm.WasmModuleHandler,
60 list_i: Sequence[int],
61 list_o: Sequence[int],
62 args: Union[Sequence[int], Sequence[Bit]], # noqa: UP007
63 args_wasm: Sequence[int] | None = None,
64 **kwargs: Any,
65) -> Circuit:
66 """
67 Add a classical function call from a wasm file to the circuit.
69 :param funcname: name of the function that is called
70 :param filehandler: wasm file or module handler to identify the wasm module
71 :param list_i: list of the number of bits in the input variables
72 :param list_o: list of the number of bits in the output variables
73 :param args: vector of circuit bits the wasm op should be added to
74 :param args_wasm: vector of wasmstates the wasm op should be added to
75 :param kwargs: additional arguments passed to :py:meth:`~.Circuit.add_gate`.
76 Allowed parameters are `opgroup`, `condition`, `condition_bits`,
77 `condition_value`
78 :return: the new :py:class:`Circuit`
79 """
81 if args_wasm is None:
82 args_wasm = [0]
84 for x in list_i:
85 if x > filehandler._int_size: # noqa: SLF001
86 raise ValueError(
87 f"only functions with i{filehandler._int_size} type are allowed" # noqa: SLF001
88 )
90 for x in list_o:
91 if x > filehandler._int_size: # noqa: SLF001
92 raise ValueError(
93 f"only functions with i{filehandler._int_size} type are allowed" # noqa: SLF001
94 )
96 if filehandler.check_function(funcname, len(list_i), len(list_o)):
97 if (len(args_wasm)) > 0: 97 ↛ 99line 97 didn't jump to line 99 because the condition on line 97 was always true
98 self._add_w_register(max(args_wasm) + 1)
99 return self._add_wasm(
100 funcname, str(filehandler), list_i, list_o, args, args_wasm, **kwargs
101 )
103 raise ValueError(f"{funcname} not found, check {filehandler!r}")
106setattr(Circuit, "add_wasm", add_wasm) # noqa: B010
109def add_wasm_to_reg( # noqa: PLR0913
110 self: Circuit,
111 funcname: str,
112 filehandler: wasm.WasmModuleHandler,
113 list_i: Sequence[BitRegister],
114 list_o: Sequence[BitRegister],
115 args_wasm: Sequence[int] | None = None,
116 **kwargs: Any,
117) -> Circuit:
118 """
119 Add a classical function call from a wasm file to the circuit.
121 :param funcname: name of the function that is called
122 :param filehandler: wasm file or module handler to identify the wasm module
123 :param list_i: list of the classical registers assigned to
124 the input variables of the function call
125 :param list_o: list of the classical registers assigned to
126 the output variables of the function call
127 :param args_wasm: vector of wasmstates the wasm op should be added to
128 :param kwargs: additional arguments passed to :py:meth:`~.Circuit.add_gate`.
129 Allowed parameters are `opgroup`, `condition`, `condition_bits`,
130 `condition_value`
131 :return: the new :py:class:`Circuit`
132 """
134 if args_wasm is None: 134 ↛ 137line 134 didn't jump to line 137 because the condition on line 134 was always true
135 args_wasm = [0]
137 if filehandler.checked:
138 for reg in list_i:
139 if reg.size > 32: # noqa: PLR2004
140 raise ValueError(
141 """wasm is only supporting 32 bit size registers,
142please use only registers of at most 32 bits"""
143 )
145 for reg in list_o:
146 if reg.size > 32: # noqa: PLR2004 146 ↛ 147line 146 didn't jump to line 147 because the condition on line 146 was never true
147 raise ValueError(
148 """wasm is only supporting 32 bit size registers,
149please use only registers of at most 32 bits"""
150 )
152 # If the filehandler has not been checked we allow it to
153 # be added without checking the function arity.
154 if not filehandler.checked or filehandler.check_function(
155 funcname, len(list_i), len(list_o)
156 ):
157 if (len(args_wasm)) > 0: 157 ↛ 159line 157 didn't jump to line 159 because the condition on line 157 was always true
158 self._add_w_register(max(args_wasm) + 1)
159 return self._add_wasm(
160 funcname, str(filehandler), list_i, list_o, args_wasm, **kwargs
161 )
163 raise ValueError(f"{funcname} not found, check {filehandler!r}")
166setattr(Circuit, "add_wasm_to_reg", add_wasm_to_reg) # noqa: B010
169def set_rng_seed(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
170 """
171 Seed an RNG from the contents of a classical register.
173 The classical register must be exactly 64 bits.
175 :param creg: register of classical bits
176 :param kwargs: additional arguments passed to :py:meth:`~.Circuit.add_gate` (allowed parameters
177 are `opgroup`, `condition`, `condition_bits` and `condition_value`)
178 :return: the new :py:class:`Circuit`
179 """
180 self._add_r_register(1)
181 if creg.size != 64: # noqa: PLR2004
182 raise ValueError(
183 f"Register passed to `set_rng_seed()` has size {creg.size} (should be 64)"
184 )
185 return self._set_rng_seed(creg, 0, **kwargs)
188setattr(Circuit, "set_rng_seed", set_rng_seed) # noqa: B010
191def set_rng_bound(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
192 """
193 Set an RNG upper bound from the contents of a classical register.
195 The classical register must be exactly 32 bits. It encodes the upper bound in
196 little-endian binary (least significant bit first). The bound is inclusive.
198 :param creg: register of classical bits
199 :param kwargs: additional arguments passed to :py:meth:`~.Circuit.add_gate` (allowed parameters
200 are `opgroup`, `condition`, `condition_bits` and `condition_value`)
201 :return: the new :py:class:`Circuit`
202 """
203 self._add_r_register(1)
204 if creg.size != 32: # noqa: PLR2004
205 raise ValueError(
206 f"Register passed to `set_rng_bound()` has size {creg.size} (should be 32)"
207 )
208 return self._set_rng_bound(creg, 0, **kwargs)
211setattr(Circuit, "set_rng_bound", set_rng_bound) # noqa: B010
214def set_rng_index(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
215 """
216 Set an RNG stream index from the contents of a classical register.
218 The classical register must be exactly 32 bits. It encodes the index in little-
219 endian binary (least significant bit first).
221 :param creg: register of classical bits
222 :param kwargs: additional arguments passed to :py:meth:`~.Circuit.add_gate` (allowed parameters
223 are `opgroup`, `condition`, `condition_bits` and `condition_value`)
224 :return: the new :py:class:`Circuit`
225 """
226 self._add_r_register(1)
227 if creg.size != 32: # noqa: PLR2004
228 raise ValueError(
229 f"Register passed to `set_rng_bound()` has size {creg.size} (should be 32)"
230 )
231 return self._set_rng_index(creg, 0, **kwargs)
234setattr(Circuit, "set_rng_index", set_rng_index) # noqa: B010
237def get_rng_num(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
238 """
239 Get RNG output into a classical register.
241 The classical register must be exactly 32 bits. After the operation it encodes the
242 output number in little-endian binary (least significant bit first).
244 :param creg: register of classical bits
245 :param kwargs: additional arguments passed to :py:meth:`~.Circuit.add_gate` (allowed parameters
246 are `opgroup`, `condition`, `condition_bits` and `condition_value`)
247 :return: the new :py:class:`Circuit`
248 """
249 self._add_r_register(1)
250 if creg.size != 32: # noqa: PLR2004
251 raise ValueError(
252 f"Register passed to `get_rng_num()` has size {creg.size} (should be 32)"
253 )
254 return self._get_rng_num(creg, 0, **kwargs)
257setattr(Circuit, "get_rng_num", get_rng_num) # noqa: B010
260def get_job_shot_num(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
261 """
262 Get shot number into a classical register.
264 The classical register must be exactly 32 bits. After the operation it encodes the
265 shot number in little-endian binary (least significant bit first).
267 :param creg: register of classical bits
268 :param kwargs: additional arguments passed to :py:meth:`~.Circuit.add_gate` (allowed parameters
269 are `opgroup`, `condition`, `condition_bits` and `condition_value`)
270 :return: the new :py:class:`Circuit`
271 """
272 self._add_r_register(1)
273 if creg.size != 32: # noqa: PLR2004
274 raise ValueError(
275 f"Register passed to `get_job_shot_num()` has size {creg.size} (should be 32)"
276 )
277 return self._get_job_shot_num(creg, **kwargs)
280setattr(Circuit, "get_job_shot_num", get_job_shot_num) # noqa: B010
283def add_clexpr_from_logicexp(
284 circ: Circuit, exp: LogicExp, output_bits: list[Bit], **kwargs: Any
285) -> Circuit:
286 """
287 Append a :py:class:`~.ClExprOp` defined in terms of a logical expression.
289 Example:
291 >>> c = Circuit()
292 >>> x_reg = c.add_c_register('x', 3)
293 >>> y_reg = c.add_c_register('y', 3)
294 >>> z_reg = c.add_c_register('z', 3)
295 >>> c.add_clexpr_from_logicexp(x_reg | y_reg, z_reg.to_list())
296 [ClExpr x[0], x[1], x[2], y[0], y[1], y[2], z[0], z[1], z[2]; ]
298 :param exp: logical expression
299 :param output_bits: list of bits in output
300 :return: the updated circuit
301 """
302 wexpr, args = wired_clexpr_from_logic_exp(exp, output_bits)
303 circ.add_clexpr(wexpr, args, **kwargs)
304 return circ
307setattr(Circuit, "add_clexpr_from_logicexp", add_clexpr_from_logicexp) # noqa: B010