Coverage for /home/runner/work/tket/tket/pytket/pytket/circuit/__init__.py: 96%
76 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-11 07:40 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-11 07:40 +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 """Add a classical function call from a wasm file to the circuit.
67 \n\n:param funcname: name of the function that is called
68 \n:param filehandler: wasm file or module handler to identify the wasm module
69 \n:param list_i: list of the number of bits in the input variables
70 \n:param list_o: list of the number of bits in the output variables
71 \n:param args: vector of circuit bits the wasm op should be added to
72 \n:param args_wasm: vector of wasmstates the wasm op should be added to
73 \n:param kwargs: additional arguments passed to `add_gate_method` .
74 Allowed parameters are `opgroup`, `condition` , `condition_bits`,
75 `condition_value`
76 \n:return: the new :py:class:`Circuit`"""
78 if args_wasm is None:
79 args_wasm = [0]
81 for x in list_i:
82 if x > filehandler._int_size: # noqa: SLF001
83 raise ValueError(
84 f"only functions with i{filehandler._int_size} type are allowed" # noqa: SLF001
85 )
87 for x in list_o:
88 if x > filehandler._int_size: # noqa: SLF001
89 raise ValueError(
90 f"only functions with i{filehandler._int_size} type are allowed" # noqa: SLF001
91 )
93 if filehandler.check_function(funcname, len(list_i), len(list_o)):
94 if (len(args_wasm)) > 0: 94 ↛ 96line 94 didn't jump to line 96 because the condition on line 94 was always true
95 self._add_w_register(max(args_wasm) + 1)
96 return self._add_wasm(
97 funcname, str(filehandler), list_i, list_o, args, args_wasm, **kwargs
98 )
100 raise ValueError(f"{funcname} not found, check {filehandler!r}")
103setattr(Circuit, "add_wasm", add_wasm) # noqa: B010
106def add_wasm_to_reg( # noqa: PLR0913
107 self: Circuit,
108 funcname: str,
109 filehandler: wasm.WasmModuleHandler,
110 list_i: Sequence[BitRegister],
111 list_o: Sequence[BitRegister],
112 args_wasm: Sequence[int] | None = None,
113 **kwargs: Any,
114) -> Circuit:
115 """Add a classical function call from a wasm file to the circuit.
116 \n\n:param funcname: name of the function that is called
117 \n:param filehandler: wasm file or module handler to identify the wasm module
118 \n:param list_i: list of the classical registers assigned to
119 the input variables of the function call
120 \n:param list_o: list of the classical registers assigned to
121 the output variables of the function call
122 \n:param args_wasm: vector of wasmstates the wasm op should be added to
123 \n:param kwargs: additional arguments passed to `add_gate_method` .
124 Allowed parameters are `opgroup`, `condition` , `condition_bits`,
125 `condition_value`
126 \n:return: the new :py:class:`Circuit`"""
128 if args_wasm is None: 128 ↛ 131line 128 didn't jump to line 131 because the condition on line 128 was always true
129 args_wasm = [0]
131 if filehandler.checked:
132 for reg in list_i:
133 if reg.size > 32: # noqa: PLR2004
134 raise ValueError(
135 """wasm is only supporting 32 bit size registers,
136please use only registers of at most 32 bits"""
137 )
139 for reg in list_o:
140 if reg.size > 32: # noqa: PLR2004 140 ↛ 141line 140 didn't jump to line 141 because the condition on line 140 was never true
141 raise ValueError(
142 """wasm is only supporting 32 bit size registers,
143please use only registers of at most 32 bits"""
144 )
146 # If the filehandler has not been checked we allow it to
147 # be added without checking the function arity.
148 if not filehandler.checked or filehandler.check_function(
149 funcname, len(list_i), len(list_o)
150 ):
151 if (len(args_wasm)) > 0: 151 ↛ 153line 151 didn't jump to line 153 because the condition on line 151 was always true
152 self._add_w_register(max(args_wasm) + 1)
153 return self._add_wasm(
154 funcname, str(filehandler), list_i, list_o, args_wasm, **kwargs
155 )
157 raise ValueError(f"{funcname} not found, check {filehandler!r}")
160setattr(Circuit, "add_wasm_to_reg", add_wasm_to_reg) # noqa: B010
163def set_rng_seed(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
164 """Seed an RNG from the contents of a classical register.
166 The classical register must be exactly 64 bits.
168 :param creg: register of classical bits
169 :param kwargs: additional arguments passed to `add_gate_method` (allowed parameters
170 are `opgroup`, `condition` , `condition_bits` and `condition_value`)
171 :return: the new :py:class:`Circuit`
172 """
173 self._add_r_register(1)
174 if creg.size != 64: # noqa: PLR2004
175 raise ValueError(
176 f"Register passed to `set_rng_seed()` has size {creg.size} (should be 64)"
177 )
178 return self._set_rng_seed(creg, 0, **kwargs)
181setattr(Circuit, "set_rng_seed", set_rng_seed) # noqa: B010
184def set_rng_bound(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
185 """Set an RNG upper bound from the contents of a classical register.
187 The classical register must be exactly 32 bits. It encodes the upper bound in
188 little-endian binary (least significant bit first). The bound is inclusive.
190 :param creg: register of classical bits
191 :param kwargs: additional arguments passed to `add_gate_method` (allowed parameters
192 are `opgroup`, `condition` , `condition_bits` and `condition_value`)
193 :return: the new :py:class:`Circuit`
194 """
195 self._add_r_register(1)
196 if creg.size != 32: # noqa: PLR2004
197 raise ValueError(
198 f"Register passed to `set_rng_bound()` has size {creg.size} (should be 32)"
199 )
200 return self._set_rng_bound(creg, 0, **kwargs)
203setattr(Circuit, "set_rng_bound", set_rng_bound) # noqa: B010
206def set_rng_index(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
207 """Set an RNG stream index from the contents of a classical register.
209 The classical register must be exactly 32 bits. It encodes the index in little-
210 endian binary (least significant bit first).
212 :param creg: register of classical bits
213 :param kwargs: additional arguments passed to `add_gate_method` (allowed parameters
214 are `opgroup`, `condition` , `condition_bits` and `condition_value`)
215 :return: the new :py:class:`Circuit`
216 """
217 self._add_r_register(1)
218 if creg.size != 32: # noqa: PLR2004
219 raise ValueError(
220 f"Register passed to `set_rng_bound()` has size {creg.size} (should be 32)"
221 )
222 return self._set_rng_index(creg, 0, **kwargs)
225setattr(Circuit, "set_rng_index", set_rng_index) # noqa: B010
228def get_rng_num(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
229 """Get RNG output into a classical register.
231 The classical register must be exactly 32 bits. After the operation it encodes the
232 output number in little-endian binary (least significant bit first).
234 :param creg: register of classical bits
235 :param kwargs: additional arguments passed to `add_gate_method` (allowed parameters
236 are `opgroup`, `condition` , `condition_bits` and `condition_value`)
237 :return: the new :py:class:`Circuit`
238 """
239 self._add_r_register(1)
240 if creg.size != 32: # noqa: PLR2004
241 raise ValueError(
242 f"Register passed to `get_rng_num()` has size {creg.size} (should be 32)"
243 )
244 return self._get_rng_num(creg, 0, **kwargs)
247setattr(Circuit, "get_rng_num", get_rng_num) # noqa: B010
250def get_job_shot_num(self: Circuit, creg: BitRegister, **kwargs: Any) -> Circuit:
251 """Get shot number into a classical register.
253 The classical register must be exactly 32 bits. After the operation it encodes the
254 shot number in little-endian binary (least significant bit first).
256 :param creg: register of classical bits
257 :param kwargs: additional arguments passed to `add_gate_method` (allowed parameters
258 are `opgroup`, `condition` , `condition_bits` and `condition_value`)
259 :return: the new :py:class:`Circuit`
260 """
261 self._add_r_register(1)
262 if creg.size != 32: # noqa: PLR2004
263 raise ValueError(
264 f"Register passed to `get_job_shot_num()` has size {creg.size} (should be 32)"
265 )
266 return self._get_job_shot_num(creg, **kwargs)
269setattr(Circuit, "get_job_shot_num", get_job_shot_num) # noqa: B010
272def add_clexpr_from_logicexp(
273 circ: Circuit, exp: LogicExp, output_bits: list[Bit], **kwargs: Any
274) -> Circuit:
275 """Append a :py:class:`~.ClExprOp` defined in terms of a logical expression.
276 \n\nExample:
277 \n>>> c = Circuit()\n>>> x_reg = c.add_c_register('x', 3)\n>>> y_reg = c.add_c_register('y', 3)\n>>> z_reg = c.add_c_register('z', 3)\n>>> c.add_clexpr_from_logicexp(x_reg | y_reg, z_reg.to_list())\n[ClExpr x[0], x[1], x[2], y[0], y[1], y[2], z[0], z[1], z[2]; ]
278 \n:param exp: logical expression
279 \n:param output_bits: list of bits in output
280 \n:return: the updated circuit"""
281 wexpr, args = wired_clexpr_from_logic_exp(exp, output_bits)
282 circ.add_clexpr(wexpr, args, **kwargs)
283 return circ
286setattr(Circuit, "add_clexpr_from_logicexp", add_clexpr_from_logicexp) # noqa: B010