classiq 0.37.1__py3-none-any.whl → 0.39.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. classiq/__init__.py +23 -24
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +1 -1
  3. classiq/_analyzer_extras/interactive_hardware.py +3 -3
  4. classiq/_internals/api_wrapper.py +37 -17
  5. classiq/_internals/async_utils.py +1 -74
  6. classiq/_internals/authentication/device.py +9 -4
  7. classiq/_internals/authentication/password_manager.py +25 -10
  8. classiq/_internals/authentication/token_manager.py +2 -2
  9. classiq/_internals/client.py +24 -6
  10. classiq/_internals/jobs.py +10 -7
  11. classiq/analyzer/analyzer.py +29 -29
  12. classiq/analyzer/analyzer_utilities.py +5 -5
  13. classiq/analyzer/rb.py +4 -5
  14. classiq/analyzer/show_interactive_hack.py +6 -6
  15. classiq/applications/__init__.py +1 -8
  16. classiq/applications/chemistry/__init__.py +6 -0
  17. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +9 -16
  18. classiq/applications/combinatorial_helpers/allowed_constraints.py +20 -0
  19. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
  20. classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
  21. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +150 -0
  22. classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
  23. classiq/applications/combinatorial_helpers/encoding_utils.py +122 -0
  24. classiq/applications/combinatorial_helpers/memory.py +77 -0
  25. classiq/applications/combinatorial_helpers/optimization_model.py +162 -0
  26. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
  27. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +75 -0
  28. classiq/applications/combinatorial_helpers/py.typed +0 -0
  29. classiq/applications/combinatorial_helpers/pyomo_utils.py +245 -0
  30. classiq/applications/combinatorial_helpers/solvers/__init__.py +0 -0
  31. classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
  32. classiq/applications/combinatorial_helpers/transformations/__init__.py +0 -0
  33. classiq/applications/combinatorial_helpers/transformations/encoding.py +187 -0
  34. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +142 -0
  35. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +122 -0
  36. classiq/applications/combinatorial_helpers/transformations/penalty.py +32 -0
  37. classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
  38. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +75 -0
  39. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +88 -0
  40. classiq/applications/combinatorial_optimization/__init__.py +13 -2
  41. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +134 -0
  42. classiq/applications/finance/__init__.py +3 -2
  43. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +27 -30
  44. classiq/applications/grover/__init__.py +11 -0
  45. classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +20 -91
  46. classiq/applications/libraries/__init__.py +0 -0
  47. classiq/applications/libraries/qmci_library.py +35 -0
  48. classiq/applications/qnn/circuit_utils.py +2 -2
  49. classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
  50. classiq/applications/qnn/types.py +2 -2
  51. classiq/applications/qsvm/__init__.py +5 -1
  52. classiq/applications/qsvm/qsvm.py +4 -7
  53. classiq/applications/qsvm/qsvm_data_generation.py +2 -5
  54. classiq/exceptions.py +43 -1
  55. classiq/execution/all_hardware_devices.py +13 -0
  56. classiq/executor.py +12 -10
  57. classiq/interface/_version.py +1 -1
  58. classiq/interface/analyzer/analysis_params.py +6 -3
  59. classiq/interface/analyzer/result.py +12 -8
  60. classiq/interface/applications/qsvm.py +17 -3
  61. classiq/interface/ast_node.py +23 -0
  62. classiq/interface/backend/backend_preferences.py +4 -2
  63. classiq/interface/backend/pydantic_backend.py +3 -1
  64. classiq/interface/backend/quantum_backend_providers.py +1 -0
  65. classiq/interface/chemistry/fermionic_operator.py +15 -13
  66. classiq/interface/chemistry/ground_state_problem.py +18 -3
  67. classiq/interface/chemistry/molecule.py +8 -6
  68. classiq/interface/chemistry/operator.py +20 -14
  69. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -1
  70. classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
  71. classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
  72. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -2
  73. classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
  74. classiq/interface/combinatorial_optimization/examples/mht.py +8 -3
  75. classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
  76. classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
  77. classiq/interface/combinatorial_optimization/examples/set_cover.py +2 -1
  78. classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
  79. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
  80. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +9 -3
  81. classiq/interface/executor/aws_execution_cost.py +4 -3
  82. classiq/interface/executor/estimation.py +2 -2
  83. classiq/interface/executor/execution_preferences.py +5 -34
  84. classiq/interface/executor/execution_request.py +15 -48
  85. classiq/interface/executor/optimizer_preferences.py +22 -13
  86. classiq/interface/executor/{quantum_program.py → quantum_code.py} +21 -15
  87. classiq/interface/executor/quantum_instruction_set.py +2 -1
  88. classiq/interface/executor/register_initialization.py +1 -3
  89. classiq/interface/executor/result.py +41 -10
  90. classiq/interface/executor/vqe_result.py +2 -2
  91. classiq/interface/finance/function_input.py +17 -4
  92. classiq/interface/finance/gaussian_model_input.py +3 -1
  93. classiq/interface/finance/log_normal_model_input.py +3 -1
  94. classiq/interface/finance/model_input.py +2 -0
  95. classiq/interface/generator/amplitude_loading.py +6 -3
  96. classiq/interface/generator/application_apis/__init__.py +1 -0
  97. classiq/interface/generator/application_apis/arithmetic_declarations.py +14 -0
  98. classiq/interface/generator/arith/argument_utils.py +14 -4
  99. classiq/interface/generator/arith/arithmetic.py +3 -1
  100. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +12 -13
  101. classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -1
  102. classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -2
  103. classiq/interface/generator/arith/arithmetic_expression_validator.py +16 -2
  104. classiq/interface/generator/arith/arithmetic_operations.py +5 -10
  105. classiq/interface/generator/arith/ast_node_rewrite.py +1 -1
  106. classiq/interface/generator/arith/binary_ops.py +202 -54
  107. classiq/interface/generator/arith/extremum_operations.py +5 -3
  108. classiq/interface/generator/arith/logical_ops.py +4 -2
  109. classiq/interface/generator/arith/machine_precision.py +3 -0
  110. classiq/interface/generator/arith/number_utils.py +34 -44
  111. classiq/interface/generator/arith/register_user_input.py +21 -1
  112. classiq/interface/generator/arith/unary_ops.py +16 -25
  113. classiq/interface/generator/builtin_api_builder.py +0 -5
  114. classiq/interface/generator/chemistry_function_params.py +4 -4
  115. classiq/interface/generator/commuting_pauli_exponentiation.py +3 -1
  116. classiq/interface/generator/compiler_keywords.py +4 -0
  117. classiq/interface/generator/complex_type.py +3 -10
  118. classiq/interface/generator/constant.py +2 -3
  119. classiq/interface/generator/control_state.py +5 -3
  120. classiq/interface/generator/credit_risk_example/linear_gci.py +10 -3
  121. classiq/interface/generator/credit_risk_example/weighted_adder.py +14 -4
  122. classiq/interface/generator/expressions/atomic_expression_functions.py +5 -3
  123. classiq/interface/generator/expressions/evaluated_expression.py +18 -4
  124. classiq/interface/generator/expressions/expression.py +3 -5
  125. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +33 -0
  126. classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
  127. classiq/interface/generator/finance.py +1 -1
  128. classiq/interface/generator/function_params.py +7 -6
  129. classiq/interface/generator/functions/__init__.py +2 -2
  130. classiq/interface/generator/functions/builtins/__init__.py +15 -0
  131. classiq/interface/generator/functions/builtins/core_library/__init__.py +14 -0
  132. classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
  133. classiq/interface/generator/functions/builtins/internal_operators.py +62 -0
  134. classiq/interface/generator/functions/{core_lib_declarations/quantum_functions/std_lib_functions.py → builtins/open_lib_functions.py} +612 -219
  135. classiq/interface/generator/functions/builtins/quantum_operators.py +37 -0
  136. classiq/interface/generator/functions/classical_type.py +2 -4
  137. classiq/interface/generator/functions/foreign_function_definition.py +12 -4
  138. classiq/interface/generator/functions/function_declaration.py +2 -2
  139. classiq/interface/generator/functions/function_implementation.py +8 -4
  140. classiq/interface/generator/functions/native_function_definition.py +4 -2
  141. classiq/interface/generator/functions/register.py +4 -2
  142. classiq/interface/generator/functions/register_mapping_data.py +14 -10
  143. classiq/interface/generator/generated_circuit_data.py +2 -2
  144. classiq/interface/generator/grover_operator.py +5 -3
  145. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +5 -1
  146. classiq/interface/generator/hardware/hardware_data.py +6 -4
  147. classiq/interface/generator/hardware_efficient_ansatz.py +25 -8
  148. classiq/interface/generator/hartree_fock.py +13 -3
  149. classiq/interface/generator/linear_pauli_rotations.py +3 -1
  150. classiq/interface/generator/mcu.py +5 -3
  151. classiq/interface/generator/mcx.py +7 -5
  152. classiq/interface/generator/model/classical_main_validator.py +1 -1
  153. classiq/interface/generator/model/constraints.py +2 -1
  154. classiq/interface/generator/model/model.py +12 -20
  155. classiq/interface/generator/model/preferences/preferences.py +4 -3
  156. classiq/interface/generator/oracles/custom_oracle.py +4 -2
  157. classiq/interface/generator/oracles/oracle_abc.py +2 -2
  158. classiq/interface/generator/qpe.py +6 -4
  159. classiq/interface/generator/qsvm.py +5 -8
  160. classiq/interface/generator/quantum_function_call.py +21 -16
  161. classiq/interface/generator/{generated_circuit.py → quantum_program.py} +10 -14
  162. classiq/interface/generator/range_types.py +3 -1
  163. classiq/interface/generator/slice_parsing_utils.py +8 -3
  164. classiq/interface/generator/standard_gates/controlled_standard_gates.py +4 -2
  165. classiq/interface/generator/state_preparation/metrics.py +2 -1
  166. classiq/interface/generator/state_preparation/state_preparation.py +7 -5
  167. classiq/interface/generator/state_propagator.py +16 -5
  168. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  169. classiq/interface/generator/types/struct_declaration.py +10 -7
  170. classiq/interface/generator/ucc.py +6 -4
  171. classiq/interface/generator/unitary_gate.py +7 -3
  172. classiq/interface/generator/validations/flow_graph.py +6 -4
  173. classiq/interface/generator/validations/validator_functions.py +6 -4
  174. classiq/interface/hardware.py +2 -2
  175. classiq/interface/helpers/custom_encoders.py +3 -0
  176. classiq/interface/helpers/pydantic_model_helpers.py +0 -6
  177. classiq/interface/helpers/validation_helpers.py +1 -1
  178. classiq/interface/helpers/versioned_model.py +4 -1
  179. classiq/interface/ide/show.py +2 -2
  180. classiq/interface/jobs.py +72 -3
  181. classiq/interface/model/bind_operation.py +18 -11
  182. classiq/interface/model/call_synthesis_data.py +68 -0
  183. classiq/interface/model/classical_if.py +13 -0
  184. classiq/interface/model/classical_parameter_declaration.py +2 -3
  185. classiq/interface/model/control.py +16 -0
  186. classiq/interface/model/handle_binding.py +3 -2
  187. classiq/interface/model/inplace_binary_operation.py +2 -2
  188. classiq/interface/model/invert.py +10 -0
  189. classiq/interface/model/model.py +29 -22
  190. classiq/interface/model/native_function_definition.py +3 -5
  191. classiq/interface/model/power.py +12 -0
  192. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +9 -4
  193. classiq/interface/model/quantum_expressions/control_state.py +2 -2
  194. classiq/interface/model/quantum_function_call.py +33 -142
  195. classiq/interface/model/quantum_function_declaration.py +8 -0
  196. classiq/interface/model/quantum_if_operation.py +4 -5
  197. classiq/interface/model/quantum_lambda_function.py +58 -0
  198. classiq/{quantum_register.py → interface/model/quantum_register.py} +17 -9
  199. classiq/interface/model/quantum_statement.py +3 -2
  200. classiq/interface/model/quantum_type.py +58 -59
  201. classiq/interface/model/quantum_variable_declaration.py +3 -3
  202. classiq/interface/model/repeat.py +13 -0
  203. classiq/interface/model/resolvers/function_call_resolver.py +26 -0
  204. classiq/interface/model/statement_block.py +49 -0
  205. classiq/interface/model/validations/handles_validator.py +16 -18
  206. classiq/interface/model/within_apply_operation.py +11 -0
  207. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
  208. classiq/interface/server/routes.py +5 -4
  209. classiq/qmod/__init__.py +13 -6
  210. classiq/qmod/builtins/classical_execution_primitives.py +27 -36
  211. classiq/qmod/builtins/classical_functions.py +22 -12
  212. classiq/qmod/builtins/functions.py +272 -328
  213. classiq/qmod/builtins/operations.py +171 -35
  214. classiq/qmod/builtins/structs.py +15 -15
  215. classiq/qmod/cfunc.py +42 -0
  216. classiq/qmod/classical_function.py +6 -14
  217. classiq/qmod/declaration_inferrer.py +12 -21
  218. classiq/qmod/expression_query.py +23 -0
  219. classiq/qmod/model_state_container.py +2 -0
  220. classiq/qmod/native/__init__.py +0 -0
  221. classiq/qmod/native/expression_to_qmod.py +189 -0
  222. classiq/qmod/native/pretty_printer.py +340 -0
  223. classiq/qmod/qfunc.py +27 -0
  224. classiq/qmod/qmod_constant.py +100 -0
  225. classiq/qmod/qmod_parameter.py +36 -13
  226. classiq/qmod/qmod_struct.py +3 -3
  227. classiq/qmod/qmod_variable.py +148 -31
  228. classiq/qmod/quantum_callable.py +1 -0
  229. classiq/qmod/quantum_expandable.py +18 -19
  230. classiq/qmod/quantum_function.py +41 -8
  231. classiq/qmod/symbolic.py +48 -5
  232. classiq/qmod/symbolic_expr.py +9 -0
  233. classiq/qmod/utilities.py +13 -0
  234. classiq/qmod/write_qmod.py +39 -0
  235. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/METADATA +2 -1
  236. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/RECORD +244 -225
  237. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/WHEEL +1 -1
  238. classiq/applications/benchmarking/__init__.py +0 -9
  239. classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
  240. classiq/applications/numpy_utils.py +0 -37
  241. classiq/applications_model_constructors/__init__.py +0 -17
  242. classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
  243. classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
  244. classiq/builtin_functions/__init__.py +0 -43
  245. classiq/builtin_functions/amplitude_loading.py +0 -3
  246. classiq/builtin_functions/binary_ops.py +0 -1
  247. classiq/builtin_functions/exponentiation.py +0 -5
  248. classiq/builtin_functions/qpe.py +0 -4
  249. classiq/builtin_functions/qsvm.py +0 -7
  250. classiq/builtin_functions/range_types.py +0 -5
  251. classiq/builtin_functions/standard_gates.py +0 -1
  252. classiq/builtin_functions/state_preparation.py +0 -6
  253. classiq/builtin_functions/suzuki_trotter.py +0 -3
  254. classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
  255. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  256. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
  257. classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
  258. classiq/interface/generator/types/combinatorial_problem.py +0 -26
  259. classiq/interface/model/numeric_reinterpretation.py +0 -25
  260. classiq/interface/model/operator_synthesis_data.py +0 -48
  261. classiq/model/__init__.py +0 -14
  262. classiq/model/composite_function_generator.py +0 -33
  263. classiq/model/function_handler.py +0 -466
  264. classiq/model/function_handler.pyi +0 -152
  265. classiq/model/logic_flow.py +0 -149
  266. classiq/model/logic_flow_change_handler.py +0 -71
  267. classiq/model/model.py +0 -246
  268. classiq/quantum_functions/__init__.py +0 -17
  269. classiq/quantum_functions/annotation_parser.py +0 -207
  270. classiq/quantum_functions/decorators.py +0 -22
  271. classiq/quantum_functions/function_library.py +0 -181
  272. classiq/quantum_functions/function_parser.py +0 -74
  273. classiq/quantum_functions/quantum_function.py +0 -236
  274. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
  275. /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
  276. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/pauli_helpers/__init__.py} +0 -0
  277. /classiq/{applications_model_constructors → applications}/libraries/ampltitude_estimation_library.py +0 -0
  278. /classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +0 -0
  279. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/atomic_quantum_functions.py +0 -0
  280. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/exponentiation_functions.py +0 -0
@@ -1,11 +1,9 @@
1
- from typing import List
2
-
3
1
  import pydantic
4
2
 
5
- from classiq.interface.model.quantum_function_call import ConcreteQuantumStatement
6
3
  from classiq.interface.model.quantum_function_declaration import (
7
4
  QuantumFunctionDeclaration,
8
5
  )
6
+ from classiq.interface.model.statement_block import StatementBlock
9
7
  from classiq.interface.model.validations.handles_validator import HandleValidator
10
8
  from classiq.interface.model.variable_declaration_statement import (
11
9
  VariableDeclarationStatement,
@@ -22,7 +20,7 @@ class NativeFunctionDefinition(QuantumFunctionDeclaration):
22
20
  objects from other classes.
23
21
  """
24
22
 
25
- body: List[ConcreteQuantumStatement] = pydantic.Field(
23
+ body: StatementBlock = pydantic.Field(
26
24
  default_factory=list, description="List of function calls to perform."
27
25
  )
28
26
 
@@ -33,6 +31,6 @@ class NativeFunctionDefinition(QuantumFunctionDeclaration):
33
31
  if isinstance(statement, VariableDeclarationStatement):
34
32
  handle_validator.handle_variable_declaration(statement)
35
33
  else:
36
- handle_validator.handle_call(statement)
34
+ handle_validator.handle_operation(statement)
37
35
 
38
36
  handle_validator.report_errored_handles(ClassiqValueError)
@@ -0,0 +1,12 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from classiq.interface.generator.expressions.expression import Expression
4
+ from classiq.interface.model.quantum_statement import QuantumOperation
5
+
6
+ if TYPE_CHECKING:
7
+ from classiq.interface.model.statement_block import StatementBlock
8
+
9
+
10
+ class Power(QuantumOperation):
11
+ power: Expression
12
+ body: "StatementBlock"
@@ -36,9 +36,14 @@ class AmplitudeLoadingOperation(QuantumAssignmentOperation):
36
36
  ) -> Mapping[
37
37
  str, Union[SlicedHandleBinding, SubscriptHandleBinding, HandleBinding]
38
38
  ]:
39
- if len(self.var_handles) == 0:
40
- return dict()
41
- return {AMPLITUDE_IO_NAME: self.var_handles[0]}
39
+ inouts = {self.result_name(): self.result_var}
40
+ if len(self.var_handles) == 1:
41
+ inouts[AMPLITUDE_IO_NAME] = self.var_handles[0]
42
+ return inouts
43
+
44
+ @property
45
+ def wiring_outputs(self) -> Mapping[str, HandleBinding]:
46
+ return {}
42
47
 
43
48
  def initialize_var_types(
44
49
  self,
@@ -50,7 +55,7 @@ class AmplitudeLoadingOperation(QuantumAssignmentOperation):
50
55
  var_type = var_types[self.var_handles[0].name]
51
56
  if not (
52
57
  isinstance(var_type, QuantumNumeric)
53
- and var_type.fraction_digits == var_type.size_in_bits
58
+ and var_type.fraction_digits_value == var_type.size_in_bits
54
59
  ):
55
60
  raise ClassiqValueError(VAR_DOMAIN_ILLEGAL)
56
61
  super().initialize_var_types(var_types, machine_precision)
@@ -4,7 +4,7 @@ from classiq.exceptions import ClassiqValueError
4
4
  def min_unsigned_bit_length(number: int) -> int:
5
5
  if number < 0:
6
6
  raise ClassiqValueError(
7
- f"Quantum register is not signed but control value " # noqa: B907
7
+ f"Quantum register is not signed but control value "
8
8
  f"'{number}' is negative"
9
9
  )
10
10
  return 1 if number == 0 else number.bit_length()
@@ -28,7 +28,7 @@ def to_twos_complement(value: int, bits: int, is_signed: bool) -> str:
28
28
  required_bits = min_bit_length(value, is_signed)
29
29
  if bits < required_bits:
30
30
  raise ClassiqValueError(
31
- f"Cannot express '{value}' using {bits} bits: " # noqa: B907
31
+ f"Cannot express '{value}' using {bits} bits: "
32
32
  f"at least {required_bits} bits are required"
33
33
  )
34
34
  if value >= 0:
@@ -1,49 +1,35 @@
1
1
  import itertools
2
2
  import re
3
- from typing import Any, Dict, List, Mapping, Optional, Sequence, Set, Union
3
+ from typing import Any, Dict, List, Mapping, Optional, Set, Type, Union
4
4
 
5
5
  import pydantic
6
- from pydantic import BaseModel
7
6
 
7
+ from classiq.interface.ast_node import ASTNode
8
8
  from classiq.interface.generator.expressions.expression import Expression
9
- from classiq.interface.generator.function_params import NAME_REGEX
10
- from classiq.interface.generator.functions import FunctionDeclaration
9
+ from classiq.interface.generator.functions.function_declaration import (
10
+ FunctionDeclaration,
11
+ )
11
12
  from classiq.interface.generator.functions.port_declaration import (
12
13
  PortDeclarationDirection,
13
14
  )
14
- from classiq.interface.generator.quantum_function_call import (
15
- BAD_CALL_NAME_ERROR_MSG,
16
- SUFFIX_MARKER,
17
- randomize_suffix,
18
- )
19
- from classiq.interface.helpers.custom_pydantic_types import PydanticNonEmptyString
20
- from classiq.interface.model.bind_operation import BindOperation
15
+ from classiq.interface.model.call_synthesis_data import CallSynthesisData
21
16
  from classiq.interface.model.handle_binding import (
22
17
  HandleBinding,
23
18
  SlicedHandleBinding,
24
19
  SubscriptHandleBinding,
25
20
  )
26
- from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
27
- from classiq.interface.model.numeric_reinterpretation import (
28
- NumericReinterpretationOperation,
29
- )
30
- from classiq.interface.model.operator_synthesis_data import OperatorSynthesisData
31
- from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
32
- AmplitudeLoadingOperation,
33
- )
34
- from classiq.interface.model.quantum_expressions.arithmetic_operation import (
35
- ArithmeticOperation,
36
- )
37
21
  from classiq.interface.model.quantum_function_declaration import (
38
22
  QuantumFunctionDeclaration,
39
23
  QuantumOperandDeclaration,
40
24
  )
41
- from classiq.interface.model.quantum_if_operation import QuantumIfOperation
25
+ from classiq.interface.model.quantum_lambda_function import (
26
+ LambdaListComprehension,
27
+ QuantumCallable,
28
+ QuantumLambdaFunction,
29
+ QuantumOperand,
30
+ )
42
31
  from classiq.interface.model.quantum_statement import QuantumOperation
43
32
  from classiq.interface.model.validation_handle import get_unique_handle_names
44
- from classiq.interface.model.variable_declaration_statement import (
45
- VariableDeclarationStatement,
46
- )
47
33
 
48
34
  from classiq.exceptions import ClassiqError, ClassiqValueError
49
35
 
@@ -91,8 +77,13 @@ def _validate_no_duplicated_handles(
91
77
  def _validate_no_mixing_sliced_and_whole_handles(
92
78
  inouts: Mapping[str, HandleBinding],
93
79
  ) -> None:
80
+ def _treat_subscript_as_slice(type_: Type[HandleBinding]) -> Type[HandleBinding]:
81
+ if type_ == SubscriptHandleBinding:
82
+ return SlicedHandleBinding
83
+ return type_
84
+
94
85
  inout_handle_names_to_types = {
95
- handle_name: {type(handle) for handle in handles}
86
+ handle_name: {_treat_subscript_as_slice(type(handle)) for handle in handles}
96
87
  for handle_name, handles in itertools.groupby(
97
88
  inouts.values(), lambda handle: handle.name
98
89
  )
@@ -108,10 +99,16 @@ def _validate_no_mixing_sliced_and_whole_handles(
108
99
  )
109
100
 
110
101
 
111
- ArgValue = Union[Expression, "QuantumOperand", SlicedHandleBinding, HandleBinding]
102
+ ArgValue = Union[
103
+ Expression,
104
+ QuantumOperand,
105
+ SlicedHandleBinding,
106
+ SubscriptHandleBinding,
107
+ HandleBinding,
108
+ ]
112
109
 
113
110
 
114
- class OperandIdentifier(BaseModel):
111
+ class OperandIdentifier(ASTNode):
115
112
  name: str
116
113
  index: Expression
117
114
 
@@ -121,13 +118,6 @@ class QuantumFunctionCall(QuantumOperation):
121
118
  description="The function that is called"
122
119
  )
123
120
  params: Dict[str, Expression] = pydantic.Field(default_factory=dict)
124
- release_by_inverse: bool = pydantic.Field(
125
- default=False, description="Release zero inputs in inverse call."
126
- )
127
- should_control: bool = pydantic.Field(
128
- default=True,
129
- description="False value indicates this call shouldn't be controlled even if the flow is controlled.",
130
- )
131
121
  inputs: Dict[str, HandleBinding] = pydantic.Field(
132
122
  default_factory=dict,
133
123
  description="A mapping from the input name to the wire it connects to",
@@ -142,12 +132,7 @@ class QuantumFunctionCall(QuantumOperation):
142
132
  default_factory=dict,
143
133
  description="A mapping from the output name to the wire it connects to",
144
134
  )
145
- name: PydanticNonEmptyString = pydantic.Field(
146
- default=None,
147
- description="The name of the function instance. "
148
- "If not set, determined automatically.",
149
- )
150
- operands: Dict[str, "QuantumOperand"] = pydantic.Field(
135
+ operands: Dict[str, QuantumOperand] = pydantic.Field(
151
136
  description="Function calls passed to the operator",
152
137
  default_factory=dict,
153
138
  )
@@ -157,8 +142,8 @@ class QuantumFunctionCall(QuantumOperation):
157
142
  default=None
158
143
  )
159
144
 
160
- _operator_synthesis_data: OperatorSynthesisData = pydantic.PrivateAttr(
161
- default_factory=OperatorSynthesisData
145
+ _synthesis_data: CallSynthesisData = pydantic.PrivateAttr(
146
+ default_factory=CallSynthesisData
162
147
  )
163
148
 
164
149
  @property
@@ -207,33 +192,6 @@ class QuantumFunctionCall(QuantumOperation):
207
192
  result.extend(self.outputs.values())
208
193
  return result
209
194
 
210
- def __eq__(self, other: Any) -> bool:
211
- return isinstance(other, QuantumFunctionCall) and self.name == other.name
212
-
213
- def __hash__(self) -> int:
214
- return hash(self.name)
215
-
216
- @pydantic.validator("name", pre=True, always=True)
217
- def _create_name(cls, name: Optional[str], values: Dict[str, Any]) -> str:
218
- """
219
- generates a name to a user defined-functions as follows:
220
- <function_name>_<SUFFIX_MARKER>_<random_suffix>
221
- """
222
- if name is not None:
223
- match = re.fullmatch(pattern=NAME_REGEX, string=name)
224
- if match is None:
225
- raise ValueError(BAD_CALL_NAME_ERROR_MSG)
226
- return name
227
-
228
- function = values.get("function")
229
- if isinstance(function, OperandIdentifier):
230
- function = function.name
231
-
232
- suffix = f"{SUFFIX_MARKER}_{randomize_suffix()}"
233
- if not function:
234
- return name if name else suffix
235
- return f"{function}_{suffix}"
236
-
237
195
  @property
238
196
  def pos_param_args(self) -> Dict[str, Expression]:
239
197
  return dict(
@@ -324,17 +282,11 @@ class QuantumFunctionCall(QuantumOperation):
324
282
  qlambda.set_op_decl(op_decl)
325
283
 
326
284
  @property
327
- def operator_synthesis_data(self) -> OperatorSynthesisData:
328
- return self._operator_synthesis_data
329
-
330
- def set_operator_synthesis_data(
331
- self, operator_synthesis_data: OperatorSynthesisData
332
- ) -> None:
333
- self._operator_synthesis_data = operator_synthesis_data
285
+ def synthesis_data(self) -> CallSynthesisData:
286
+ return self._synthesis_data
334
287
 
335
- @staticmethod
336
- def _has_repetitions(name_list: Sequence[str]) -> bool:
337
- return len(set(name_list)) < len(name_list)
288
+ def merge_synthesis_data(self, other: CallSynthesisData) -> None:
289
+ self._synthesis_data = self._synthesis_data.merge(other)
338
290
 
339
291
  @pydantic.root_validator()
340
292
  def validate_handles(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@@ -349,67 +301,6 @@ class QuantumFunctionCall(QuantumOperation):
349
301
  return values
350
302
 
351
303
 
352
- ConcreteQuantumStatement = Union[
353
- QuantumFunctionCall,
354
- ArithmeticOperation,
355
- AmplitudeLoadingOperation,
356
- VariableDeclarationStatement,
357
- BindOperation,
358
- NumericReinterpretationOperation,
359
- InplaceBinaryOperation,
360
- QuantumIfOperation,
361
- ]
362
-
363
-
364
- class QuantumLambdaFunction(BaseModel):
365
- """
366
- The definition of an anonymous function passed as operand to higher-level functions
367
- """
368
-
369
- rename_params: Dict[str, str] = pydantic.Field(
370
- default_factory=dict,
371
- description="Mapping of the declared param to the actual variable name used ",
372
- )
373
-
374
- body: List[ConcreteQuantumStatement] = pydantic.Field(
375
- description="A list of function calls passed to the operator"
376
- )
377
-
378
- _func_decl: Optional[QuantumOperandDeclaration] = pydantic.PrivateAttr(default=None)
379
-
380
- @property
381
- def func_decl(self) -> Optional[QuantumOperandDeclaration]:
382
- return self._func_decl
383
-
384
- def set_op_decl(self, fd: QuantumOperandDeclaration) -> None:
385
- self._func_decl = fd
386
-
387
-
388
- class LambdaListComprehension(BaseModel):
389
- """
390
- Specification of a list of lambda functions iteratively
391
- """
392
-
393
- count: Expression = pydantic.Field(
394
- description="The number of lambda functions in the list"
395
- )
396
-
397
- index_var: str = pydantic.Field(
398
- description="The name of the integer variable holding the iteration index"
399
- )
400
-
401
- func: QuantumLambdaFunction = pydantic.Field(
402
- description="A lambda function definition replicated for index values 0 to count-1"
403
- )
404
-
405
-
406
- QuantumCallable = Union[str, QuantumLambdaFunction]
407
- QuantumOperand = Union[QuantumCallable, List[QuantumCallable], LambdaListComprehension]
408
-
409
- QuantumFunctionCall.update_forward_refs()
410
- QuantumIfOperation.update_forward_refs(QuantumOperand=QuantumOperand)
411
-
412
-
413
304
  def get_lambda_defs(operand: QuantumOperand) -> List[QuantumCallable]:
414
305
  if isinstance(operand, list):
415
306
  return operand
@@ -108,6 +108,14 @@ class QuantumFunctionDeclaration(FunctionDeclaration):
108
108
  ) -> None:
109
109
  pass
110
110
 
111
+ @property
112
+ def port_names(self) -> List[str]:
113
+ return list(self.port_declarations.keys())
114
+
115
+ @property
116
+ def operand_names(self) -> List[str]:
117
+ return list(self.operand_declarations.keys())
118
+
111
119
  def ports_by_direction(
112
120
  self, direction: PortDirection
113
121
  ) -> Mapping[str, PortDeclaration]:
@@ -5,7 +5,7 @@ from sympy import Equality
5
5
  from sympy.core.numbers import Integer
6
6
 
7
7
  from classiq.interface.generator.expressions.expression import Expression
8
- from classiq.interface.generator.expressions.qmod_qnum_proxy import QmodQNumProxy
8
+ from classiq.interface.generator.expressions.qmod_qscalar_proxy import QmodQNumProxy
9
9
  from classiq.interface.model.quantum_expressions.control_state import (
10
10
  min_bit_length,
11
11
  to_twos_complement,
@@ -17,8 +17,7 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
17
17
  from classiq.exceptions import ClassiqValueError
18
18
 
19
19
  if TYPE_CHECKING:
20
- from classiq.interface.model.quantum_function_call import QuantumOperand
21
-
20
+ from classiq.interface.model.statement_block import StatementBlock
22
21
 
23
22
  QUANTUM_IF_INOUT_NAME = "ctrl"
24
23
  QUANTUM_IF_CONDITION_ARG_ERROR_MESSAGE_FORMAT = (
@@ -27,8 +26,8 @@ QUANTUM_IF_CONDITION_ARG_ERROR_MESSAGE_FORMAT = (
27
26
  )
28
27
 
29
28
 
30
- class QuantumIfOperation(QuantumExpressionOperation):
31
- then: "QuantumOperand"
29
+ class QuantumIf(QuantumExpressionOperation):
30
+ then: "StatementBlock"
32
31
  _ctrl: Optional[QmodQNumProxy] = pydantic.PrivateAttr(
33
32
  default=None,
34
33
  )
@@ -0,0 +1,58 @@
1
+ from typing import TYPE_CHECKING, Dict, List, Optional, Union
2
+
3
+ import pydantic
4
+
5
+ from classiq.interface.ast_node import ASTNode
6
+ from classiq.interface.generator.expressions.expression import Expression
7
+ from classiq.interface.model.quantum_function_declaration import (
8
+ QuantumOperandDeclaration,
9
+ )
10
+
11
+ if TYPE_CHECKING:
12
+ from classiq.interface.model.statement_block import StatementBlock
13
+
14
+
15
+ class QuantumLambdaFunction(ASTNode):
16
+ """
17
+ The definition of an anonymous function passed as operand to higher-level functions
18
+ """
19
+
20
+ rename_params: Dict[str, str] = pydantic.Field(
21
+ default_factory=dict,
22
+ description="Mapping of the declared param to the actual variable name used ",
23
+ )
24
+
25
+ body: "StatementBlock" = pydantic.Field(
26
+ description="A list of function calls passed to the operator"
27
+ )
28
+
29
+ _func_decl: Optional[QuantumOperandDeclaration] = pydantic.PrivateAttr(default=None)
30
+
31
+ @property
32
+ def func_decl(self) -> Optional[QuantumOperandDeclaration]:
33
+ return self._func_decl
34
+
35
+ def set_op_decl(self, fd: QuantumOperandDeclaration) -> None:
36
+ self._func_decl = fd
37
+
38
+
39
+ class LambdaListComprehension(ASTNode):
40
+ """
41
+ Specification of a list of lambda functions iteratively
42
+ """
43
+
44
+ count: Expression = pydantic.Field(
45
+ description="The number of lambda functions in the list"
46
+ )
47
+
48
+ index_var: str = pydantic.Field(
49
+ description="The name of the integer variable holding the iteration index"
50
+ )
51
+
52
+ func: QuantumLambdaFunction = pydantic.Field(
53
+ description="A lambda function definition replicated for index values 0 to count-1"
54
+ )
55
+
56
+
57
+ QuantumCallable = Union[str, QuantumLambdaFunction]
58
+ QuantumOperand = Union[QuantumCallable, List[QuantumCallable], LambdaListComprehension]
@@ -1,7 +1,15 @@
1
1
  import itertools
2
2
  import sys
3
- from typing import _GenericAlias # type: ignore[attr-defined]
4
- from typing import Any, Dict, List, Optional, Type, Union
3
+ from typing import ( # type: ignore[attr-defined]
4
+ Any,
5
+ Dict,
6
+ Iterator,
7
+ List,
8
+ Optional,
9
+ Type,
10
+ Union,
11
+ _GenericAlias,
12
+ )
5
13
 
6
14
  from classiq.interface.generator.arith.register_user_input import (
7
15
  RegisterArithmeticInfo,
@@ -19,7 +27,7 @@ if sys.version_info >= (3, 9):
19
27
  # This class is used for QReg, to support type-hint initialization
20
28
  # Due to the `size` property of QReg
21
29
  class QRegGenericAlias(_GenericAlias, _root=True): # type: ignore[call-arg]
22
- def __call__(self, *args, **kwargs):
30
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
23
31
  arith_info = {}
24
32
  if self.size is not None:
25
33
  arith_info["size"] = self.size
@@ -48,13 +56,13 @@ class QRegGenericAlias(_GenericAlias, _root=True): # type: ignore[call-arg]
48
56
 
49
57
  @property
50
58
  def integer_places(self) -> Optional[int]:
51
- if len(self.__args__) in (1, 2) and type(self.__args__[0]) is int:
59
+ if len(self.__args__) in (1, 2) and isinstance(self.__args__[0], int):
52
60
  return self.__args__[0]
53
61
  return None
54
62
 
55
63
  @property
56
64
  def fraction_places(self) -> Optional[int]:
57
- if len(self.__args__) == 2 and type(self.__args__[1]) is int:
65
+ if len(self.__args__) == 2 and isinstance(self.__args__[1], int):
58
66
  return self.__args__[1]
59
67
  return None
60
68
 
@@ -102,7 +110,7 @@ class QReg:
102
110
  )
103
111
  self._qubits[key] = value._qubits[0] if isinstance(key, int) else value._qubits # type: ignore[call-overload]
104
112
 
105
- def __iter__(self):
113
+ def __iter__(self) -> Iterator["QReg"]:
106
114
  return iter([self[idx] for idx in range(len(self))])
107
115
 
108
116
  def __eq__(self, other: Any) -> bool:
@@ -136,7 +144,7 @@ class QReg:
136
144
 
137
145
  def __class_getitem__(cls, params: Any) -> QRegGenericAlias:
138
146
  # Supporting python 3.7+, thus returning `typing._GenericAlias` instead of `types.GenericAlias`
139
- if type(params) is int:
147
+ if isinstance(params, int):
140
148
  return QRegGenericAlias(cls, params)
141
149
 
142
150
  raise ClassiqQRegError(f"Invalid size: {params} ; int required")
@@ -171,8 +179,8 @@ class QSFixed(QReg):
171
179
  if (
172
180
  type(params) is tuple
173
181
  and len(params) == 2
174
- and type(params[0]) is int
175
- and type(params[1]) is int
182
+ and isinstance(params[0], int)
183
+ and isinstance(params[1], int)
176
184
  ):
177
185
  return QRegGenericAlias(cls, params)
178
186
 
@@ -1,7 +1,8 @@
1
1
  from typing import Mapping, Union
2
2
 
3
- from pydantic import BaseModel, Extra
3
+ from pydantic import Extra
4
4
 
5
+ from classiq.interface.ast_node import ASTNode
5
6
  from classiq.interface.model.handle_binding import (
6
7
  HandleBinding,
7
8
  SlicedHandleBinding,
@@ -9,7 +10,7 @@ from classiq.interface.model.handle_binding import (
9
10
  )
10
11
 
11
12
 
12
- class QuantumStatement(BaseModel):
13
+ class QuantumStatement(ASTNode):
13
14
  class Config:
14
15
  extra = Extra.forbid
15
16