classiq 0.93.0__py3-none-any.whl → 0.99.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 (315) hide show
  1. classiq/__init__.py +11 -19
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +7 -7
  3. classiq/_analyzer_extras/interactive_hardware.py +19 -12
  4. classiq/_internals/api_wrapper.py +31 -142
  5. classiq/_internals/async_utils.py +4 -7
  6. classiq/_internals/authentication/auth0.py +41 -15
  7. classiq/_internals/authentication/authorization_code.py +9 -0
  8. classiq/_internals/authentication/authorization_flow.py +41 -0
  9. classiq/_internals/authentication/device.py +33 -52
  10. classiq/_internals/authentication/hybrid_flow.py +19 -0
  11. classiq/_internals/authentication/password_manager.py +13 -13
  12. classiq/_internals/authentication/token_manager.py +9 -9
  13. classiq/_internals/client.py +17 -44
  14. classiq/_internals/config.py +19 -5
  15. classiq/_internals/help.py +1 -2
  16. classiq/_internals/host_checker.py +3 -3
  17. classiq/_internals/jobs.py +14 -14
  18. classiq/_internals/type_validation.py +3 -3
  19. classiq/analyzer/analyzer.py +18 -18
  20. classiq/analyzer/rb.py +17 -8
  21. classiq/analyzer/show_interactive_hack.py +1 -1
  22. classiq/applications/__init__.py +2 -2
  23. classiq/applications/chemistry/__init__.py +0 -30
  24. classiq/applications/chemistry/op_utils.py +4 -4
  25. classiq/applications/chemistry/problems.py +3 -3
  26. classiq/applications/chemistry/ucc.py +1 -2
  27. classiq/applications/chemistry/z2_symmetries.py +4 -4
  28. classiq/applications/combinatorial_helpers/allowed_constraints.py +1 -3
  29. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +2 -1
  30. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +2 -2
  31. classiq/applications/combinatorial_helpers/encoding_mapping.py +2 -3
  32. classiq/applications/combinatorial_helpers/encoding_utils.py +2 -2
  33. classiq/applications/combinatorial_helpers/optimization_model.py +3 -4
  34. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +2 -2
  35. classiq/applications/combinatorial_helpers/pyomo_utils.py +8 -8
  36. classiq/applications/combinatorial_helpers/sympy_utils.py +1 -3
  37. classiq/applications/combinatorial_helpers/transformations/encoding.py +3 -3
  38. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +1 -2
  39. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -3
  40. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +4 -6
  41. classiq/applications/combinatorial_optimization/combinatorial_problem.py +15 -10
  42. classiq/applications/hamiltonian/pauli_decomposition.py +6 -4
  43. classiq/applications/iqae/iqae.py +14 -11
  44. classiq/applications/qnn/datasets/dataset_base_classes.py +6 -6
  45. classiq/applications/qnn/datasets/dataset_parity.py +6 -6
  46. classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
  47. classiq/applications/qnn/qlayer.py +9 -8
  48. classiq/applications/qnn/torch_utils.py +5 -6
  49. classiq/applications/qnn/types.py +2 -1
  50. classiq/applications/qsp/__init__.py +20 -2
  51. classiq/applications/qsp/qsp.py +238 -10
  52. classiq/applications/qsvm/qsvm_data_generation.py +1 -2
  53. classiq/evaluators/classical_expression.py +0 -4
  54. classiq/evaluators/parameter_types.py +10 -8
  55. classiq/evaluators/qmod_annotated_expression.py +31 -26
  56. classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +14 -14
  57. classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +2 -1
  58. classiq/evaluators/qmod_expression_visitors/sympy_wrappers.py +8 -8
  59. classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +4 -4
  60. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +14 -4
  61. classiq/evaluators/qmod_node_evaluators/list_evaluation.py +2 -2
  62. classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +3 -3
  63. classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +9 -9
  64. classiq/evaluators/qmod_node_evaluators/utils.py +6 -6
  65. classiq/evaluators/qmod_type_inference/classical_type_inference.py +9 -10
  66. classiq/evaluators/qmod_type_inference/quantum_type_inference.py +5 -5
  67. classiq/execution/__init__.py +0 -3
  68. classiq/execution/execution_session.py +28 -21
  69. classiq/execution/jobs.py +26 -26
  70. classiq/execution/qnn.py +1 -2
  71. classiq/execution/user_budgets.py +71 -37
  72. classiq/executor.py +1 -3
  73. classiq/interface/_version.py +1 -1
  74. classiq/interface/analyzer/analysis_params.py +4 -4
  75. classiq/interface/analyzer/cytoscape_graph.py +3 -3
  76. classiq/interface/analyzer/result.py +4 -4
  77. classiq/interface/ast_node.py +3 -3
  78. classiq/interface/backend/backend_preferences.py +26 -50
  79. classiq/interface/backend/ionq/ionq_quantum_program.py +5 -5
  80. classiq/interface/backend/provider_config/__init__.py +0 -0
  81. classiq/interface/backend/provider_config/provider_config.py +8 -0
  82. classiq/interface/backend/provider_config/providers/__init__.py +0 -0
  83. classiq/interface/backend/provider_config/providers/alice_bob.py +47 -0
  84. classiq/interface/backend/provider_config/providers/aqt.py +16 -0
  85. classiq/interface/backend/provider_config/providers/azure.py +37 -0
  86. classiq/interface/backend/provider_config/providers/braket.py +39 -0
  87. classiq/interface/backend/provider_config/providers/ibm.py +26 -0
  88. classiq/interface/backend/provider_config/providers/ionq.py +22 -0
  89. classiq/interface/backend/quantum_backend_providers.py +20 -2
  90. classiq/interface/chemistry/ansatz_library.py +3 -5
  91. classiq/interface/chemistry/operator.py +3 -3
  92. classiq/interface/combinatorial_optimization/examples/knapsack.py +2 -4
  93. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +1 -2
  94. classiq/interface/compression_utils.py +2 -3
  95. classiq/interface/debug_info/debug_info.py +8 -7
  96. classiq/interface/exceptions.py +6 -7
  97. classiq/interface/execution/primitives.py +6 -6
  98. classiq/interface/executor/estimate_cost.py +1 -1
  99. classiq/interface/executor/execution_preferences.py +3 -5
  100. classiq/interface/executor/execution_request.py +10 -10
  101. classiq/interface/executor/execution_result.py +1 -2
  102. classiq/interface/executor/quantum_code.py +8 -8
  103. classiq/interface/executor/result.py +28 -18
  104. classiq/interface/executor/user_budget.py +25 -17
  105. classiq/interface/executor/vqe_result.py +5 -6
  106. classiq/interface/generator/ansatz_library.py +6 -8
  107. classiq/interface/generator/application_apis/__init__.py +0 -3
  108. classiq/interface/generator/arith/arithmetic.py +2 -2
  109. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +2 -3
  110. classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -5
  111. classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -4
  112. classiq/interface/generator/arith/arithmetic_expression_validator.py +12 -15
  113. classiq/interface/generator/arith/arithmetic_operations.py +4 -6
  114. classiq/interface/generator/arith/arithmetic_param_getters.py +70 -107
  115. classiq/interface/generator/arith/arithmetic_result_builder.py +4 -4
  116. classiq/interface/generator/arith/ast_node_rewrite.py +8 -4
  117. classiq/interface/generator/arith/binary_ops.py +15 -40
  118. classiq/interface/generator/arith/logical_ops.py +2 -3
  119. classiq/interface/generator/arith/number_utils.py +2 -2
  120. classiq/interface/generator/arith/register_user_input.py +3 -3
  121. classiq/interface/generator/arith/unary_ops.py +2 -2
  122. classiq/interface/generator/circuit_code/circuit_code.py +8 -10
  123. classiq/interface/generator/circuit_code/types_and_constants.py +1 -1
  124. classiq/interface/generator/complex_type.py +2 -2
  125. classiq/interface/generator/copy.py +1 -3
  126. classiq/interface/generator/expressions/atomic_expression_functions.py +0 -5
  127. classiq/interface/generator/expressions/evaluated_expression.py +2 -3
  128. classiq/interface/generator/expressions/expression.py +2 -2
  129. classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -7
  130. classiq/interface/generator/function_param_list.py +0 -40
  131. classiq/interface/generator/function_params.py +5 -6
  132. classiq/interface/generator/functions/classical_function_declaration.py +2 -2
  133. classiq/interface/generator/functions/classical_type.py +3 -3
  134. classiq/interface/generator/functions/type_modifier.py +0 -15
  135. classiq/interface/generator/functions/type_name.py +2 -2
  136. classiq/interface/generator/generated_circuit_data.py +14 -18
  137. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +2 -4
  138. classiq/interface/generator/hardware/hardware_data.py +8 -8
  139. classiq/interface/generator/hardware_efficient_ansatz.py +9 -9
  140. classiq/interface/generator/mcu.py +3 -3
  141. classiq/interface/generator/mcx.py +3 -3
  142. classiq/interface/generator/model/constraints.py +34 -5
  143. classiq/interface/generator/model/preferences/preferences.py +15 -21
  144. classiq/interface/generator/model/quantum_register.py +7 -10
  145. classiq/interface/generator/noise_properties.py +3 -7
  146. classiq/interface/generator/parameters.py +1 -1
  147. classiq/interface/generator/partitioned_register.py +1 -2
  148. classiq/interface/generator/preferences/qasm_to_qmod_params.py +11 -0
  149. classiq/interface/generator/quantum_function_call.py +9 -12
  150. classiq/interface/generator/quantum_program.py +10 -23
  151. classiq/interface/generator/range_types.py +3 -3
  152. classiq/interface/generator/slice_parsing_utils.py +4 -5
  153. classiq/interface/generator/standard_gates/standard_gates.py +2 -4
  154. classiq/interface/generator/synthesis_execution_parameter.py +1 -3
  155. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +9 -0
  156. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +2 -3
  157. classiq/interface/generator/transpiler_basis_gates.py +12 -4
  158. classiq/interface/generator/types/builtin_enum_declarations.py +0 -145
  159. classiq/interface/generator/types/compilation_metadata.py +12 -1
  160. classiq/interface/generator/types/enum_declaration.py +2 -1
  161. classiq/interface/generator/validations/flow_graph.py +3 -3
  162. classiq/interface/generator/visitor.py +10 -12
  163. classiq/interface/hardware.py +2 -3
  164. classiq/interface/helpers/classproperty.py +2 -2
  165. classiq/interface/helpers/custom_encoders.py +2 -1
  166. classiq/interface/helpers/custom_pydantic_types.py +1 -1
  167. classiq/interface/helpers/text_utils.py +1 -4
  168. classiq/interface/ide/visual_model.py +6 -5
  169. classiq/interface/interface_version.py +1 -1
  170. classiq/interface/jobs.py +3 -3
  171. classiq/interface/model/allocate.py +4 -4
  172. classiq/interface/model/block.py +6 -2
  173. classiq/interface/model/bounds.py +3 -3
  174. classiq/interface/model/classical_if.py +4 -0
  175. classiq/interface/model/control.py +8 -1
  176. classiq/interface/model/inplace_binary_operation.py +2 -2
  177. classiq/interface/model/invert.py +4 -0
  178. classiq/interface/model/model.py +4 -4
  179. classiq/interface/model/model_visitor.py +40 -1
  180. classiq/interface/model/parameter.py +1 -3
  181. classiq/interface/model/port_declaration.py +1 -1
  182. classiq/interface/model/power.py +4 -0
  183. classiq/interface/model/quantum_expressions/quantum_expression.py +1 -2
  184. classiq/interface/model/quantum_function_call.py +3 -6
  185. classiq/interface/model/quantum_function_declaration.py +1 -0
  186. classiq/interface/model/quantum_lambda_function.py +4 -4
  187. classiq/interface/model/quantum_statement.py +11 -4
  188. classiq/interface/model/quantum_type.py +14 -14
  189. classiq/interface/model/repeat.py +4 -0
  190. classiq/interface/model/skip_control.py +4 -0
  191. classiq/interface/model/validation_handle.py +2 -3
  192. classiq/interface/model/variable_declaration_statement.py +2 -2
  193. classiq/interface/model/within_apply_operation.py +4 -0
  194. classiq/interface/pretty_print/expression_to_qmod.py +3 -4
  195. classiq/interface/server/routes.py +0 -16
  196. classiq/interface/source_reference.py +3 -4
  197. classiq/model_expansions/arithmetic.py +11 -7
  198. classiq/model_expansions/arithmetic_compute_result_attrs.py +30 -27
  199. classiq/model_expansions/capturing/captured_vars.py +3 -3
  200. classiq/model_expansions/capturing/mangling_utils.py +1 -2
  201. classiq/model_expansions/closure.py +12 -11
  202. classiq/model_expansions/function_builder.py +14 -6
  203. classiq/model_expansions/generative_functions.py +7 -12
  204. classiq/model_expansions/interpreters/base_interpreter.py +3 -7
  205. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
  206. classiq/model_expansions/interpreters/generative_interpreter.py +5 -3
  207. classiq/model_expansions/quantum_operations/allocate.py +4 -4
  208. classiq/model_expansions/quantum_operations/assignment_result_processor.py +2 -4
  209. classiq/model_expansions/quantum_operations/call_emitter.py +31 -37
  210. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +2 -2
  211. classiq/model_expansions/quantum_operations/emitter.py +3 -5
  212. classiq/model_expansions/quantum_operations/expression_evaluator.py +3 -3
  213. classiq/model_expansions/quantum_operations/skip_control_verifier.py +1 -2
  214. classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
  215. classiq/model_expansions/scope.py +7 -7
  216. classiq/model_expansions/scope_initialization.py +4 -0
  217. classiq/model_expansions/visitors/symbolic_param_inference.py +6 -6
  218. classiq/model_expansions/visitors/uncomputation_signature_inference.py +328 -0
  219. classiq/model_expansions/visitors/variable_references.py +15 -14
  220. classiq/open_library/functions/__init__.py +28 -11
  221. classiq/open_library/functions/amplitude_loading.py +81 -0
  222. classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
  223. classiq/open_library/functions/grover.py +8 -10
  224. classiq/open_library/functions/lcu.py +47 -18
  225. classiq/open_library/functions/modular_exponentiation.py +93 -8
  226. classiq/open_library/functions/qsvt.py +66 -79
  227. classiq/open_library/functions/qsvt_temp.py +536 -0
  228. classiq/open_library/functions/state_preparation.py +130 -27
  229. classiq/qmod/__init__.py +6 -4
  230. classiq/qmod/builtins/classical_execution_primitives.py +4 -23
  231. classiq/qmod/builtins/classical_functions.py +1 -42
  232. classiq/qmod/builtins/enums.py +15 -153
  233. classiq/qmod/builtins/functions/__init__.py +9 -18
  234. classiq/qmod/builtins/functions/allocation.py +25 -4
  235. classiq/qmod/builtins/functions/arithmetic.py +22 -27
  236. classiq/qmod/builtins/functions/exponentiation.py +51 -2
  237. classiq/qmod/builtins/functions/mcx_func.py +7 -0
  238. classiq/qmod/builtins/functions/standard_gates.py +46 -27
  239. classiq/qmod/builtins/operations.py +165 -79
  240. classiq/qmod/builtins/structs.py +24 -91
  241. classiq/qmod/cfunc.py +3 -2
  242. classiq/qmod/classical_function.py +2 -1
  243. classiq/qmod/cparam.py +2 -8
  244. classiq/qmod/create_model_function.py +7 -7
  245. classiq/qmod/declaration_inferrer.py +33 -30
  246. classiq/qmod/expression_query.py +7 -4
  247. classiq/qmod/model_state_container.py +2 -2
  248. classiq/qmod/native/pretty_printer.py +25 -14
  249. classiq/qmod/pretty_print/expression_to_python.py +5 -3
  250. classiq/qmod/pretty_print/pretty_printer.py +39 -17
  251. classiq/qmod/python_classical_type.py +40 -13
  252. classiq/qmod/qfunc.py +124 -19
  253. classiq/qmod/qmod_constant.py +2 -2
  254. classiq/qmod/qmod_parameter.py +5 -2
  255. classiq/qmod/qmod_variable.py +47 -46
  256. classiq/qmod/quantum_callable.py +18 -13
  257. classiq/qmod/quantum_expandable.py +31 -26
  258. classiq/qmod/quantum_function.py +84 -36
  259. classiq/qmod/semantics/annotation/call_annotation.py +5 -5
  260. classiq/qmod/semantics/error_manager.py +12 -14
  261. classiq/qmod/semantics/lambdas.py +1 -2
  262. classiq/qmod/semantics/validation/types_validation.py +1 -2
  263. classiq/qmod/symbolic.py +2 -4
  264. classiq/qmod/utilities.py +13 -20
  265. classiq/qmod/write_qmod.py +3 -4
  266. classiq/quantum_program.py +1 -3
  267. classiq/synthesis.py +11 -7
  268. {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/METADATA +2 -3
  269. {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/RECORD +271 -299
  270. {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/WHEEL +1 -1
  271. classiq/applications/chemistry/ansatz_parameters.py +0 -29
  272. classiq/applications/chemistry/chemistry_execution_parameters.py +0 -16
  273. classiq/applications/chemistry/chemistry_model_constructor.py +0 -532
  274. classiq/applications/chemistry/ground_state_problem.py +0 -42
  275. classiq/applications/qsvm/__init__.py +0 -8
  276. classiq/applications/qsvm/qsvm.py +0 -11
  277. classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -129
  278. classiq/execution/iqcc.py +0 -128
  279. classiq/interface/applications/qsvm.py +0 -117
  280. classiq/interface/chemistry/elements.py +0 -120
  281. classiq/interface/chemistry/fermionic_operator.py +0 -208
  282. classiq/interface/chemistry/ground_state_problem.py +0 -132
  283. classiq/interface/chemistry/ground_state_result.py +0 -8
  284. classiq/interface/chemistry/molecule.py +0 -71
  285. classiq/interface/execution/iqcc.py +0 -44
  286. classiq/interface/generator/application_apis/chemistry_declarations.py +0 -69
  287. classiq/interface/generator/application_apis/entangler_declarations.py +0 -29
  288. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
  289. classiq/interface/generator/chemistry_function_params.py +0 -50
  290. classiq/interface/generator/entangler_params.py +0 -72
  291. classiq/interface/generator/entanglers.py +0 -14
  292. classiq/interface/generator/hamiltonian_evolution/qdrift.py +0 -27
  293. classiq/interface/generator/hartree_fock.py +0 -26
  294. classiq/interface/generator/hva.py +0 -22
  295. classiq/interface/generator/linear_pauli_rotations.py +0 -92
  296. classiq/interface/generator/qft.py +0 -37
  297. classiq/interface/generator/qsvm.py +0 -96
  298. classiq/interface/generator/state_preparation/__init__.py +0 -14
  299. classiq/interface/generator/state_preparation/bell_state_preparation.py +0 -27
  300. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +0 -28
  301. classiq/interface/generator/state_preparation/distributions.py +0 -53
  302. classiq/interface/generator/state_preparation/exponential_state_preparation.py +0 -14
  303. classiq/interface/generator/state_preparation/ghz_state_preparation.py +0 -14
  304. classiq/interface/generator/state_preparation/metrics.py +0 -41
  305. classiq/interface/generator/state_preparation/state_preparation.py +0 -113
  306. classiq/interface/generator/state_preparation/state_preparation_abc.py +0 -24
  307. classiq/interface/generator/state_preparation/uniform_distibution_state_preparation.py +0 -13
  308. classiq/interface/generator/state_preparation/w_state_preparation.py +0 -13
  309. classiq/interface/generator/ucc.py +0 -74
  310. classiq/interface/helpers/backward_compatibility.py +0 -9
  311. classiq/model_expansions/transformers/type_modifier_inference.py +0 -392
  312. classiq/open_library/functions/lookup_table.py +0 -58
  313. classiq/qmod/builtins/functions/chemistry.py +0 -123
  314. classiq/qmod/builtins/functions/qsvm.py +0 -24
  315. {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  from collections.abc import Mapping
2
- from typing import Optional, Union, cast
2
+ from typing import cast
3
3
 
4
4
  import black
5
5
 
@@ -108,7 +108,7 @@ class VariableDeclarationAssignment(Visitor):
108
108
 
109
109
  def visit_QuantumBitvector(
110
110
  self, qtype: QuantumBitvector
111
- ) -> tuple[str, Optional[list[str]]]:
111
+ ) -> tuple[str, list[str] | None]:
112
112
  self.pretty_printer._imports["QArray"] = 1
113
113
 
114
114
  element_type = self.pretty_printer.visit(qtype.element_type)
@@ -118,7 +118,7 @@ class VariableDeclarationAssignment(Visitor):
118
118
 
119
119
  def visit_QuantumNumeric(
120
120
  self, qtype: QuantumNumeric
121
- ) -> tuple[str, Optional[list[str]]]:
121
+ ) -> tuple[str, list[str] | None]:
122
122
  self.pretty_printer._imports["QNum"] = 1
123
123
  return "QNum", self.pretty_printer._get_qnum_properties(qtype)
124
124
 
@@ -130,12 +130,12 @@ class PythonPrettyPrinter(ModelVisitor):
130
130
  def __init__(self, decimal_precision: int = DEFAULT_DECIMAL_PRECISION) -> None:
131
131
  self._level = 0
132
132
  self._decimal_precision = decimal_precision
133
- self._imports = {"qfunc": 1}
133
+ self._imports: dict[str, int] = {}
134
134
  self._import_enum = False
135
135
  self._import_dataclass = False
136
136
  self._import_annotated = False
137
137
  self._symbolic_imports: dict[str, int] = dict()
138
- self._functions: Optional[Mapping[str, QuantumFunctionDeclaration]] = None
138
+ self._functions: Mapping[str, QuantumFunctionDeclaration] | None = None
139
139
  self._compilation_metadata: dict[str, CompilationMetadata] = dict()
140
140
 
141
141
  def visit(self, node: NodeType) -> str:
@@ -204,16 +204,33 @@ class PythonPrettyPrinter(ModelVisitor):
204
204
  )
205
205
 
206
206
  def _get_qfunc_decorator(self, func_decl: QuantumFunctionDeclaration) -> str:
207
- no_unchecked_decorator = "@qfunc"
207
+ if func_decl.permutation:
208
+ decorator = "@qperm"
209
+ self._imports["qperm"] = 1
210
+ else:
211
+ decorator = "@qfunc"
212
+ self._imports["qfunc"] = 1
213
+
208
214
  if func_decl.name not in self._compilation_metadata:
209
- return no_unchecked_decorator
210
- unchecked = self._compilation_metadata[func_decl.name].unchecked
211
- if len(unchecked) == 0:
212
- return no_unchecked_decorator
215
+ return decorator
216
+
217
+ metadata = self._compilation_metadata[func_decl.name]
218
+
219
+ decorator_params: list[str] = []
220
+ if metadata.disable_perm_check:
221
+ decorator_params.append("disable_perm_check=True")
213
222
 
214
- unchecked_modifiers = (f'"{modifier}"' for modifier in unchecked)
215
- unchecked_list = f"[{', '.join(unchecked_modifiers)}]"
216
- return no_unchecked_decorator + f" (unchecked={unchecked_list})"
223
+ if metadata.disable_const_checks:
224
+ if metadata.disable_const_checks is True:
225
+ value = "True"
226
+ else:
227
+ value = f"[{', '.join(f'{param!r}' for param in metadata.disable_const_checks)}]"
228
+ decorator_params.append(f"disable_const_checks={value}")
229
+
230
+ if decorator_params:
231
+ return f"{decorator}({', '.join(decorator_params)})"
232
+ else:
233
+ return decorator
217
234
 
218
235
  def visit_QuantumFunctionDeclaration(
219
236
  self, func_decl: QuantumFunctionDeclaration
@@ -243,7 +260,7 @@ class PythonPrettyPrinter(ModelVisitor):
243
260
  return f"class {qstruct_decl.name}(QStruct):\n{self._visit_variables(qstruct_decl.fields)}\n"
244
261
 
245
262
  def _visit_variables(
246
- self, variables: Mapping[str, Union[ConcreteClassicalType, ConcreteQuantumType]]
263
+ self, variables: Mapping[str, ConcreteClassicalType | ConcreteQuantumType]
247
264
  ) -> str:
248
265
  self._level += 1
249
266
  variables_str = "".join(
@@ -262,7 +279,7 @@ class PythonPrettyPrinter(ModelVisitor):
262
279
  if port_decl.direction is not PortDeclarationDirection.Inout:
263
280
  self._imports[port_decl.direction.name] = 1
264
281
  var_type = f"{port_decl.direction.name}[{var_type}]"
265
- if port_decl.type_modifier in [TypeModifier.Const, TypeModifier.Permutable]:
282
+ if port_decl.type_modifier is TypeModifier.Const:
266
283
  self._imports[port_decl.type_modifier.name] = 1
267
284
  var_type = f"{port_decl.type_modifier.name}[{var_type}]"
268
285
  return var_type
@@ -394,7 +411,12 @@ class PythonPrettyPrinter(ModelVisitor):
394
411
  def visit_AnonQuantumOperandDeclaration(
395
412
  self, op_decl: AnonQuantumOperandDeclaration, no_param: bool = False
396
413
  ) -> str:
397
- qcallable_identifier = "QCallableList" if op_decl.is_list else "QCallable"
414
+ qcallable_identifier = {
415
+ (False, False): "QCallable",
416
+ (False, True): "QCallableList",
417
+ (True, False): "QPerm",
418
+ (True, True): "QPermList",
419
+ }[(op_decl.permutation, op_decl.is_list)]
398
420
  self._imports[qcallable_identifier] = 1
399
421
  args = ", ".join(
400
422
  self._visit_operand_arg_decl(arg_decl)
@@ -494,7 +516,7 @@ class PythonPrettyPrinter(ModelVisitor):
494
516
  return f"{self._indent}block({self._visit_body(block.statements)})\n"
495
517
 
496
518
  def _visit_body(
497
- self, body: StatementBlock, operand_arguments: Optional[list[str]] = None
519
+ self, body: StatementBlock, operand_arguments: list[str] | None = None
498
520
  ) -> str:
499
521
  if len(body) == 0:
500
522
  return "lambda: []"
@@ -5,7 +5,6 @@ from typing import (
5
5
  Any,
6
6
  ForwardRef,
7
7
  Literal,
8
- Optional,
9
8
  get_args,
10
9
  get_origin,
11
10
  )
@@ -15,6 +14,7 @@ from classiq.interface.generator.expressions.expression import Expression
15
14
  from classiq.interface.generator.functions.classical_type import (
16
15
  Bool,
17
16
  ClassicalArray,
17
+ ClassicalTuple,
18
18
  Integer,
19
19
  Real,
20
20
  )
@@ -22,7 +22,7 @@ from classiq.interface.generator.functions.concrete_types import ConcreteClassic
22
22
  from classiq.interface.generator.functions.type_name import Enum, Struct, TypeName
23
23
 
24
24
  from classiq.qmod.cparam import CArray, CBool, CInt, CReal
25
- from classiq.qmod.utilities import version_portable_get_args
25
+ from classiq.qmod.utilities import type_to_str, version_portable_get_args
26
26
 
27
27
  CARRAY_ERROR_MESSAGE = (
28
28
  "CArray accepts one or two generic parameters in the form "
@@ -30,10 +30,23 @@ CARRAY_ERROR_MESSAGE = (
30
30
  )
31
31
 
32
32
 
33
+ def _has_struct_or_enum(classical_type: ConcreteClassicalType) -> bool:
34
+ if isinstance(classical_type, TypeName):
35
+ return True
36
+ if isinstance(classical_type, ClassicalArray):
37
+ return _has_struct_or_enum(classical_type.element_type)
38
+ if isinstance(classical_type, ClassicalTuple):
39
+ return any(
40
+ _has_struct_or_enum(element_type)
41
+ for element_type in classical_type.element_types
42
+ )
43
+ return False
44
+
45
+
33
46
  class PythonClassicalType:
34
47
  def convert(
35
48
  self, py_type: type, nested: bool = False
36
- ) -> Optional[ConcreteClassicalType]:
49
+ ) -> ConcreteClassicalType | None:
37
50
  if py_type is int:
38
51
  return Integer().set_generative()
39
52
  elif py_type is CInt:
@@ -47,21 +60,35 @@ class PythonClassicalType:
47
60
  elif py_type is CBool:
48
61
  return Bool()
49
62
  elif get_origin(py_type) is list:
50
- element_type = self.convert(get_args(py_type)[0], nested=True)
51
- if element_type is not None:
52
- return ClassicalArray(element_type=element_type).set_generative()
63
+ element_py_type = get_args(py_type)[0]
64
+ element_type = self.convert(element_py_type, nested=True)
65
+ if element_type is None:
66
+ return None
67
+ if not element_type.is_generative and not _has_struct_or_enum(element_type):
68
+ raise ClassiqValueError(
69
+ f"Invalid type annotation: 'list' is generative but "
70
+ f"{type_to_str(element_py_type)!r} is declarative"
71
+ )
72
+ return ClassicalArray(element_type=element_type).set_generative()
53
73
  elif get_origin(py_type) is CArray:
54
74
  array_args = version_portable_get_args(py_type)
55
75
  if len(array_args) == 1:
56
- return ClassicalArray(
57
- element_type=self.convert(array_args[0], nested=True)
58
- )
76
+ length = None
59
77
  elif len(array_args) == 2:
60
- return ClassicalArray(
61
- element_type=self.convert(array_args[0], nested=True),
62
- length=Expression(expr=get_type_hint_expr(array_args[1])),
78
+ length = Expression(expr=get_type_hint_expr(array_args[1]))
79
+ else:
80
+ raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
81
+ element_type = self.convert(array_args[0], nested=True)
82
+ if element_type is None:
83
+ return None
84
+ if element_type.is_generative and not _has_struct_or_enum(element_type):
85
+ raise ClassiqValueError(
86
+ f"Invalid type annotation: 'CArray' is declarative but "
87
+ f"{type_to_str(array_args[0])!r} is generative"
63
88
  )
64
- raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
89
+ return ClassicalArray(
90
+ element_type=self.convert(array_args[0], nested=True), length=length
91
+ )
65
92
  elif inspect.isclass(py_type) and dataclasses.is_dataclass(py_type):
66
93
  return self.register_struct(py_type)
67
94
  elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
classiq/qmod/qfunc.py CHANGED
@@ -1,6 +1,9 @@
1
- from typing import Callable, Literal, Optional, Union, overload
1
+ from collections.abc import Callable
2
+ from typing import Literal, overload
2
3
 
3
- from classiq.interface.exceptions import ClassiqInternalError
4
+ from classiq.interface.exceptions import (
5
+ ClassiqInternalError,
6
+ )
4
7
 
5
8
  from classiq.qmod.global_declarative_switch import get_global_declarative_switch
6
9
  from classiq.qmod.quantum_callable import QCallable
@@ -21,7 +24,8 @@ def qfunc(
21
24
  *,
22
25
  external: Literal[True],
23
26
  synthesize_separately: Literal[False] = False,
24
- unchecked: Optional[list[str]] = None,
27
+ disable_perm_check: bool = False,
28
+ disable_const_checks: list[str] | bool = False,
25
29
  ) -> Callable[[Callable], ExternalQFunc]: ...
26
30
 
27
31
 
@@ -30,13 +34,17 @@ def qfunc(
30
34
  *,
31
35
  generative: Literal[False],
32
36
  synthesize_separately: bool = False,
33
- unchecked: Optional[list[str]] = None,
37
+ disable_perm_check: bool = False,
38
+ disable_const_checks: list[str] | bool = False,
34
39
  ) -> Callable[[Callable], QFunc]: ...
35
40
 
36
41
 
37
42
  @overload
38
43
  def qfunc(
39
- *, synthesize_separately: bool, unchecked: Optional[list[str]] = None
44
+ *,
45
+ synthesize_separately: bool,
46
+ disable_perm_check: bool = False,
47
+ disable_const_checks: list[str] | bool = False,
40
48
  ) -> Callable[[Callable], GenerativeQFunc]: ...
41
49
 
42
50
 
@@ -44,18 +52,103 @@ def qfunc(
44
52
  def qfunc(
45
53
  *,
46
54
  synthesize_separately: bool = False,
47
- unchecked: Optional[list[str]] = None,
55
+ disable_perm_check: bool = False,
56
+ disable_const_checks: list[str] | bool = False,
48
57
  ) -> Callable[[Callable], GenerativeQFunc]: ...
49
58
 
50
59
 
51
60
  def qfunc(
52
- func: Optional[Callable] = None,
61
+ func: Callable | None = None,
62
+ *,
63
+ external: bool = False,
64
+ generative: bool | None = None,
65
+ synthesize_separately: bool = False,
66
+ disable_perm_check: bool = False,
67
+ disable_const_checks: list[str] | bool = False,
68
+ ) -> Callable[[Callable], QCallable] | QCallable:
69
+ return _qfunc_inner(
70
+ func=func,
71
+ external=external,
72
+ generative=generative,
73
+ synthesize_separately=synthesize_separately,
74
+ permutation=False,
75
+ disable_perm_check=disable_perm_check,
76
+ disable_const_checks=disable_const_checks,
77
+ )
78
+
79
+
80
+ @overload
81
+ def qperm(func: Callable) -> GenerativeQFunc: ...
82
+
83
+
84
+ @overload
85
+ def qperm(
86
+ *,
87
+ external: Literal[True],
88
+ synthesize_separately: Literal[False] = False,
89
+ disable_perm_check: bool = False,
90
+ disable_const_checks: list[str] | bool = False,
91
+ ) -> Callable[[Callable], ExternalQFunc]: ...
92
+
93
+
94
+ @overload
95
+ def qperm(
96
+ *,
97
+ generative: Literal[False],
98
+ synthesize_separately: bool = False,
99
+ disable_perm_check: bool = False,
100
+ disable_const_checks: list[str] | bool = False,
101
+ ) -> Callable[[Callable], QFunc]: ...
102
+
103
+
104
+ @overload
105
+ def qperm(
106
+ *,
107
+ synthesize_separately: bool,
108
+ disable_perm_check: bool = False,
109
+ disable_const_checks: list[str] | bool = False,
110
+ ) -> Callable[[Callable], GenerativeQFunc]: ...
111
+
112
+
113
+ @overload
114
+ def qperm(
115
+ *,
116
+ synthesize_separately: bool = False,
117
+ disable_perm_check: bool = False,
118
+ disable_const_checks: list[str] | bool = False,
119
+ ) -> Callable[[Callable], GenerativeQFunc]: ...
120
+
121
+
122
+ def qperm(
123
+ func: Callable | None = None,
124
+ *,
125
+ external: bool = False,
126
+ generative: bool | None = None,
127
+ synthesize_separately: bool = False,
128
+ disable_perm_check: bool = False,
129
+ disable_const_checks: list[str] | bool = False,
130
+ ) -> Callable[[Callable], QCallable] | QCallable:
131
+ return _qfunc_inner(
132
+ func=func,
133
+ external=external,
134
+ generative=generative,
135
+ synthesize_separately=synthesize_separately,
136
+ permutation=True,
137
+ disable_perm_check=disable_perm_check,
138
+ disable_const_checks=disable_const_checks,
139
+ )
140
+
141
+
142
+ def _qfunc_inner(
53
143
  *,
144
+ func: Callable | None = None,
54
145
  external: bool = False,
55
- generative: Optional[bool] = None,
146
+ generative: bool | None = None,
56
147
  synthesize_separately: bool = False,
57
- unchecked: Optional[list[str]] = None,
58
- ) -> Union[Callable[[Callable], QCallable], QCallable]:
148
+ permutation: bool = False,
149
+ disable_perm_check: bool = False,
150
+ disable_const_checks: list[str] | bool = False,
151
+ ) -> Callable[[Callable], QCallable] | QCallable:
59
152
  if generative is None:
60
153
  generative = True
61
154
  if get_global_declarative_switch():
@@ -65,17 +158,21 @@ def qfunc(
65
158
  qfunc: BaseQFunc
66
159
 
67
160
  if external:
68
- _validate_directives(synthesize_separately, unchecked)
69
- return ExternalQFunc(func)
161
+ _validate_directives(
162
+ synthesize_separately, disable_perm_check, disable_const_checks
163
+ )
164
+ return ExternalQFunc(func, permutation=permutation)
70
165
 
71
166
  if generative:
72
- qfunc = GenerativeQFunc(func)
167
+ qfunc = GenerativeQFunc(func, permutation=permutation)
73
168
  else:
74
- qfunc = QFunc(func)
169
+ qfunc = QFunc(func, permutation=permutation)
75
170
  if synthesize_separately:
76
171
  qfunc.update_compilation_metadata(should_synthesize_separately=True)
77
- if unchecked is not None and len(unchecked) > 0:
78
- qfunc.update_compilation_metadata(unchecked=unchecked)
172
+ if disable_perm_check:
173
+ qfunc.update_compilation_metadata(disable_perm_check=disable_perm_check)
174
+ if disable_const_checks:
175
+ qfunc.update_compilation_metadata(disable_const_checks=disable_const_checks)
79
176
  return qfunc
80
177
 
81
178
  if func is not None:
@@ -84,12 +181,20 @@ def qfunc(
84
181
 
85
182
 
86
183
  def _validate_directives(
87
- synthesize_separately: bool, unchecked: Optional[list[str]] = None
184
+ synthesize_separately: bool,
185
+ disable_perm_check: bool = False,
186
+ disable_const_checks: list[str] | bool = False,
88
187
  ) -> None:
89
188
  error_msg = ""
90
189
  if synthesize_separately:
91
190
  error_msg += "External functions can't be marked as synthesized separately. \n"
92
- if unchecked is not None and len(unchecked) > 0:
93
- error_msg += "External functions can't have unchecked modifiers."
191
+ if disable_perm_check:
192
+ error_msg += (
193
+ "External functions can't have the `disable_perm_check` decorator. \n"
194
+ )
195
+ if disable_const_checks:
196
+ error_msg += (
197
+ "External functions can't have the `disable_const_checks` decorator. \n"
198
+ )
94
199
  if error_msg:
95
200
  raise ClassiqInternalError(error_msg)
@@ -1,6 +1,6 @@
1
1
  import inspect
2
2
  from dataclasses import is_dataclass
3
- from typing import TYPE_CHECKING, Any, Optional, cast, get_origin
3
+ from typing import TYPE_CHECKING, Any, cast, get_origin
4
4
 
5
5
  from classiq.interface.exceptions import ClassiqError, ClassiqValueError
6
6
  from classiq.interface.generator.constant import Constant
@@ -25,7 +25,7 @@ QMODULE_ERROR_MESSAGE = (
25
25
 
26
26
 
27
27
  class QConstant(SymbolicExpr):
28
- CURRENT_QMODULE: Optional[ModelStateContainer] = None
28
+ CURRENT_QMODULE: ModelStateContainer | None = None
29
29
 
30
30
  def __init__(self, name: str, py_type: type, value: Any) -> None:
31
31
  super().__init__(name, False)
@@ -1,4 +1,4 @@
1
- from typing import TYPE_CHECKING, Any, Union
1
+ from typing import TYPE_CHECKING, Any, NoReturn
2
2
 
3
3
  from classiq.interface.exceptions import ClassiqInternalError, ClassiqValueError
4
4
  from classiq.interface.generator.functions.classical_type import (
@@ -41,7 +41,7 @@ class CParamList(CParam):
41
41
  def __init__(
42
42
  self,
43
43
  expr: str,
44
- list_type: Union[ClassicalArray, ClassicalTuple],
44
+ list_type: ClassicalArray | ClassicalTuple,
45
45
  qmodule: ModelStateContainer,
46
46
  ) -> None:
47
47
  super().__init__(expr)
@@ -102,6 +102,9 @@ class CParamList(CParam):
102
102
  return interpret_expression(str(self.len))
103
103
  return CParamScalar(f"{self}.len")
104
104
 
105
+ def __iter__(self) -> NoReturn:
106
+ raise TypeError(f"{type(self).__name__!r} object is not iterable")
107
+
105
108
 
106
109
  class CParamStruct(CParam):
107
110
  def __init__(