Coverage for /home/runner/work/tket/tket/pytket/pytket/circuit/__init__.py: 93%

46 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-02 12:44 +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. 

14 

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.""" 

18 

19from collections.abc import Callable, Sequence 

20from typing import ( 

21 Any, 

22 Optional, 

23 Union, 

24) 

25 

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 * 

31 

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) 

39 

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) 

54 

55 

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: Optional[Sequence[int]] = None, # noqa: UP007 

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`""" 

77 

78 if args_wasm is None: 

79 args_wasm = [0] 

80 

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 ) 

86 

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 ) 

92 

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 ) 

99 

100 raise ValueError(f"{funcname} not found, check {filehandler!r}") 

101 

102 

103setattr(Circuit, "add_wasm", add_wasm) # noqa: B010 

104 

105 

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: Optional[Sequence[int]] = None, # noqa: UP007 

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`""" 

127 

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] 

130 

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 ) 

138 

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 ) 

145 

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 ) 

156 

157 raise ValueError(f"{funcname} not found, check {filehandler!r}") 

158 

159 

160setattr(Circuit, "add_wasm_to_reg", add_wasm_to_reg) # noqa: B010 

161 

162 

163def add_clexpr_from_logicexp( 

164 circ: Circuit, exp: LogicExp, output_bits: list[Bit], **kwargs: Any 

165) -> Circuit: 

166 """Append a :py:class:`~.ClExprOp` defined in terms of a logical expression. 

167 \n\nExample: 

168 \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]; ] 

169 \n:param exp: logical expression 

170 \n:param output_bits: list of bits in output 

171 \n:return: the updated circuit""" 

172 wexpr, args = wired_clexpr_from_logic_exp(exp, output_bits) 

173 circ.add_clexpr(wexpr, args, **kwargs) 

174 return circ 

175 

176 

177setattr(Circuit, "add_clexpr_from_logicexp", add_clexpr_from_logicexp) # noqa: B010