classiq 0.93.0__py3-none-any.whl → 0.100.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 (318) 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 +21 -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/generation_request.py +35 -0
  138. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +2 -4
  139. classiq/interface/generator/hardware/hardware_data.py +8 -8
  140. classiq/interface/generator/hardware_efficient_ansatz.py +9 -9
  141. classiq/interface/generator/mcu.py +3 -3
  142. classiq/interface/generator/mcx.py +3 -3
  143. classiq/interface/generator/model/constraints.py +34 -5
  144. classiq/interface/generator/model/preferences/preferences.py +15 -21
  145. classiq/interface/generator/model/quantum_register.py +7 -10
  146. classiq/interface/generator/noise_properties.py +3 -7
  147. classiq/interface/generator/parameters.py +1 -1
  148. classiq/interface/generator/partitioned_register.py +1 -2
  149. classiq/interface/generator/preferences/qasm_to_qmod_params.py +11 -0
  150. classiq/interface/generator/quantum_function_call.py +9 -12
  151. classiq/interface/generator/quantum_program.py +10 -23
  152. classiq/interface/generator/range_types.py +3 -3
  153. classiq/interface/generator/slice_parsing_utils.py +4 -5
  154. classiq/interface/generator/standard_gates/standard_gates.py +2 -4
  155. classiq/interface/generator/synthesis_execution_parameter.py +1 -3
  156. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +9 -0
  157. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +2 -3
  158. classiq/interface/generator/transpiler_basis_gates.py +10 -4
  159. classiq/interface/generator/types/builtin_enum_declarations.py +0 -145
  160. classiq/interface/generator/types/compilation_metadata.py +13 -2
  161. classiq/interface/generator/types/enum_declaration.py +2 -1
  162. classiq/interface/generator/validations/flow_graph.py +3 -3
  163. classiq/interface/generator/visitor.py +10 -12
  164. classiq/interface/hardware.py +2 -3
  165. classiq/interface/helpers/classproperty.py +2 -2
  166. classiq/interface/helpers/custom_encoders.py +2 -1
  167. classiq/interface/helpers/custom_pydantic_types.py +1 -1
  168. classiq/interface/helpers/text_utils.py +5 -4
  169. classiq/interface/ide/visual_model.py +6 -5
  170. classiq/interface/interface_version.py +1 -1
  171. classiq/interface/jobs.py +3 -3
  172. classiq/interface/model/allocate.py +4 -4
  173. classiq/interface/model/bind_operation.py +3 -0
  174. classiq/interface/model/block.py +6 -2
  175. classiq/interface/model/bounds.py +3 -3
  176. classiq/interface/model/classical_if.py +4 -0
  177. classiq/interface/model/control.py +8 -1
  178. classiq/interface/model/inplace_binary_operation.py +2 -2
  179. classiq/interface/model/invert.py +4 -0
  180. classiq/interface/model/model.py +4 -4
  181. classiq/interface/model/model_visitor.py +40 -1
  182. classiq/interface/model/parameter.py +1 -3
  183. classiq/interface/model/port_declaration.py +1 -1
  184. classiq/interface/model/power.py +4 -0
  185. classiq/interface/model/quantum_expressions/quantum_expression.py +1 -2
  186. classiq/interface/model/quantum_function_call.py +3 -6
  187. classiq/interface/model/quantum_function_declaration.py +1 -0
  188. classiq/interface/model/quantum_lambda_function.py +4 -4
  189. classiq/interface/model/quantum_statement.py +11 -4
  190. classiq/interface/model/quantum_type.py +14 -14
  191. classiq/interface/model/repeat.py +4 -0
  192. classiq/interface/model/skip_control.py +4 -0
  193. classiq/interface/model/validation_handle.py +2 -3
  194. classiq/interface/model/variable_declaration_statement.py +2 -2
  195. classiq/interface/model/within_apply_operation.py +4 -0
  196. classiq/interface/pretty_print/expression_to_qmod.py +3 -4
  197. classiq/interface/server/routes.py +0 -16
  198. classiq/interface/source_reference.py +3 -4
  199. classiq/model_expansions/arithmetic.py +11 -7
  200. classiq/model_expansions/arithmetic_compute_result_attrs.py +40 -28
  201. classiq/model_expansions/capturing/captured_vars.py +3 -3
  202. classiq/model_expansions/capturing/mangling_utils.py +1 -2
  203. classiq/model_expansions/closure.py +12 -11
  204. classiq/model_expansions/function_builder.py +14 -6
  205. classiq/model_expansions/generative_functions.py +7 -12
  206. classiq/model_expansions/interpreters/base_interpreter.py +3 -7
  207. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
  208. classiq/model_expansions/interpreters/generative_interpreter.py +5 -3
  209. classiq/model_expansions/quantum_operations/allocate.py +4 -4
  210. classiq/model_expansions/quantum_operations/assignment_result_processor.py +2 -4
  211. classiq/model_expansions/quantum_operations/call_emitter.py +31 -40
  212. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +2 -2
  213. classiq/model_expansions/quantum_operations/emitter.py +3 -5
  214. classiq/model_expansions/quantum_operations/expression_evaluator.py +3 -3
  215. classiq/model_expansions/quantum_operations/skip_control_verifier.py +1 -2
  216. classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
  217. classiq/model_expansions/scope.py +7 -7
  218. classiq/model_expansions/scope_initialization.py +4 -0
  219. classiq/model_expansions/visitors/symbolic_param_inference.py +6 -6
  220. classiq/model_expansions/visitors/uncomputation_signature_inference.py +328 -0
  221. classiq/model_expansions/visitors/variable_references.py +15 -14
  222. classiq/open_library/functions/__init__.py +41 -11
  223. classiq/open_library/functions/amplitude_loading.py +81 -0
  224. classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
  225. classiq/open_library/functions/encodings.py +182 -0
  226. classiq/open_library/functions/grover.py +8 -10
  227. classiq/open_library/functions/lcu.py +47 -18
  228. classiq/open_library/functions/modular_exponentiation.py +93 -8
  229. classiq/open_library/functions/qsvt.py +66 -79
  230. classiq/open_library/functions/qsvt_temp.py +536 -0
  231. classiq/open_library/functions/state_preparation.py +137 -31
  232. classiq/qmod/__init__.py +6 -4
  233. classiq/qmod/builtins/classical_execution_primitives.py +4 -23
  234. classiq/qmod/builtins/classical_functions.py +1 -42
  235. classiq/qmod/builtins/enums.py +15 -153
  236. classiq/qmod/builtins/functions/__init__.py +9 -18
  237. classiq/qmod/builtins/functions/allocation.py +25 -4
  238. classiq/qmod/builtins/functions/arithmetic.py +22 -27
  239. classiq/qmod/builtins/functions/exponentiation.py +51 -2
  240. classiq/qmod/builtins/functions/mcx_func.py +7 -0
  241. classiq/qmod/builtins/functions/standard_gates.py +46 -27
  242. classiq/qmod/builtins/operations.py +165 -79
  243. classiq/qmod/builtins/structs.py +24 -91
  244. classiq/qmod/cfunc.py +3 -2
  245. classiq/qmod/classical_function.py +2 -1
  246. classiq/qmod/cparam.py +2 -8
  247. classiq/qmod/create_model_function.py +7 -7
  248. classiq/qmod/declaration_inferrer.py +33 -30
  249. classiq/qmod/expression_query.py +7 -4
  250. classiq/qmod/model_state_container.py +2 -2
  251. classiq/qmod/native/pretty_printer.py +25 -14
  252. classiq/qmod/pretty_print/expression_to_python.py +5 -3
  253. classiq/qmod/pretty_print/pretty_printer.py +39 -17
  254. classiq/qmod/python_classical_type.py +40 -13
  255. classiq/qmod/qfunc.py +124 -19
  256. classiq/qmod/qmod_constant.py +2 -2
  257. classiq/qmod/qmod_parameter.py +5 -2
  258. classiq/qmod/qmod_variable.py +48 -47
  259. classiq/qmod/quantum_callable.py +18 -13
  260. classiq/qmod/quantum_expandable.py +31 -26
  261. classiq/qmod/quantum_function.py +84 -36
  262. classiq/qmod/semantics/annotation/call_annotation.py +5 -5
  263. classiq/qmod/semantics/error_manager.py +23 -15
  264. classiq/qmod/semantics/lambdas.py +1 -2
  265. classiq/qmod/semantics/validation/types_validation.py +1 -2
  266. classiq/qmod/symbolic.py +2 -4
  267. classiq/qmod/utilities.py +13 -20
  268. classiq/qmod/write_qmod.py +3 -4
  269. classiq/quantum_program.py +1 -3
  270. classiq/synthesis.py +11 -7
  271. {classiq-0.93.0.dist-info → classiq-0.100.0.dist-info}/METADATA +2 -3
  272. {classiq-0.93.0.dist-info → classiq-0.100.0.dist-info}/RECORD +274 -300
  273. {classiq-0.93.0.dist-info → classiq-0.100.0.dist-info}/WHEEL +1 -1
  274. classiq/applications/chemistry/ansatz_parameters.py +0 -29
  275. classiq/applications/chemistry/chemistry_execution_parameters.py +0 -16
  276. classiq/applications/chemistry/chemistry_model_constructor.py +0 -532
  277. classiq/applications/chemistry/ground_state_problem.py +0 -42
  278. classiq/applications/qsvm/__init__.py +0 -8
  279. classiq/applications/qsvm/qsvm.py +0 -11
  280. classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -129
  281. classiq/execution/iqcc.py +0 -128
  282. classiq/interface/applications/qsvm.py +0 -117
  283. classiq/interface/chemistry/elements.py +0 -120
  284. classiq/interface/chemistry/fermionic_operator.py +0 -208
  285. classiq/interface/chemistry/ground_state_problem.py +0 -132
  286. classiq/interface/chemistry/ground_state_result.py +0 -8
  287. classiq/interface/chemistry/molecule.py +0 -71
  288. classiq/interface/execution/iqcc.py +0 -44
  289. classiq/interface/generator/application_apis/chemistry_declarations.py +0 -69
  290. classiq/interface/generator/application_apis/entangler_declarations.py +0 -29
  291. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
  292. classiq/interface/generator/chemistry_function_params.py +0 -50
  293. classiq/interface/generator/entangler_params.py +0 -72
  294. classiq/interface/generator/entanglers.py +0 -14
  295. classiq/interface/generator/hamiltonian_evolution/qdrift.py +0 -27
  296. classiq/interface/generator/hartree_fock.py +0 -26
  297. classiq/interface/generator/hva.py +0 -22
  298. classiq/interface/generator/linear_pauli_rotations.py +0 -92
  299. classiq/interface/generator/qft.py +0 -37
  300. classiq/interface/generator/qsvm.py +0 -96
  301. classiq/interface/generator/state_preparation/__init__.py +0 -14
  302. classiq/interface/generator/state_preparation/bell_state_preparation.py +0 -27
  303. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +0 -28
  304. classiq/interface/generator/state_preparation/distributions.py +0 -53
  305. classiq/interface/generator/state_preparation/exponential_state_preparation.py +0 -14
  306. classiq/interface/generator/state_preparation/ghz_state_preparation.py +0 -14
  307. classiq/interface/generator/state_preparation/metrics.py +0 -41
  308. classiq/interface/generator/state_preparation/state_preparation.py +0 -113
  309. classiq/interface/generator/state_preparation/state_preparation_abc.py +0 -24
  310. classiq/interface/generator/state_preparation/uniform_distibution_state_preparation.py +0 -13
  311. classiq/interface/generator/state_preparation/w_state_preparation.py +0 -13
  312. classiq/interface/generator/ucc.py +0 -74
  313. classiq/interface/helpers/backward_compatibility.py +0 -9
  314. classiq/model_expansions/transformers/type_modifier_inference.py +0 -392
  315. classiq/open_library/functions/lookup_table.py +0 -58
  316. classiq/qmod/builtins/functions/chemistry.py +0 -123
  317. classiq/qmod/builtins/functions/qsvm.py +0 -24
  318. {classiq-0.93.0.dist-info → classiq-0.100.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,182 @@
1
+ from typing import Literal
2
+
3
+ import numpy as np
4
+
5
+ from classiq.qmod.builtins.functions.allocation import free
6
+ from classiq.qmod.builtins.functions.standard_gates import CX, SWAP, X
7
+ from classiq.qmod.builtins.operations import allocate, bind, control, invert, repeat
8
+ from classiq.qmod.qfunc import qperm
9
+ from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum
10
+
11
+
12
+ def get_rewire_list(qvars: list[QBit]) -> list[QBit]:
13
+ rewire_list = qvars[int(np.log2(len(qvars))) :]
14
+ for i, qvar in enumerate(qvars[: int(np.log2(len(qvars)))]):
15
+ rewire_list.insert(2 ** (i + 1) - 1, qvar)
16
+ return rewire_list
17
+
18
+
19
+ @qperm
20
+ def inplace_binary_to_one_hot(qvar: QArray) -> None:
21
+ """
22
+ Inplace conversion of binary encoded value to one-hot encoding.
23
+ The implementation is based on https://quantumcomputing.stackexchange.com/questions/5526/garbage-free-reversible-binary-to-unary-decoder-construction.
24
+ The input is assumed to be of size 2^n, where n is the number of bits in the binary representation.
25
+ For example, the state |01000>=|2> will be converted to |00100> (one-hot for 2).
26
+
27
+ Args:
28
+ qvar: binary input array padded with 0's to be converted to one-hot encoding.
29
+ """
30
+ temp_qvars = [QBit(f"x{i}") for i in range(qvar.len)]
31
+ bind(qvar, temp_qvars) # type: ignore[arg-type]
32
+ bind(get_rewire_list(temp_qvars), qvar) # type: ignore[arg-type]
33
+
34
+ # logic
35
+ X(qvar[0])
36
+ for i in range(int(np.log2(qvar.len))):
37
+ index = 2 ** (i + 1) - 1
38
+ for j in range(2**i - 1):
39
+ control(qvar[index], lambda i=i, j=j: SWAP(qvar[j], qvar[j + 2**i])) # type: ignore[misc]
40
+ for j in range(2**i - 1):
41
+ CX(qvar[j + 2**i], qvar[index])
42
+
43
+ CX(qvar[index], qvar[index - 2**i])
44
+
45
+
46
+ @qperm
47
+ def inplace_one_hot_to_unary(qvar: QArray) -> None:
48
+ """
49
+ Inplace conversion of one-hot encoded value to unary encoding.
50
+ The input is assumed to be of size n, where n is the number of bits in the one-hot representation.
51
+ The remaining unary representation will at the higher n-1 bits, where the lsb is cleared to 0.
52
+ For example, the state |0010> (one-hot for 2) will be converted to |0>|110> (unary for 2).
53
+
54
+ Args:
55
+ qvar: one-hot input array to be converted to unary encoding.
56
+ """
57
+ # fill with 1s after the leading 1 bit
58
+ repeat(qvar.len - 1, lambda i: CX(qvar[qvar.len - i - 1], qvar[qvar.len - i - 2]))
59
+ # clear the 0 bit, to be excluded from the unary encoding
60
+ X(qvar[0])
61
+
62
+
63
+ @qperm
64
+ def one_hot_to_unary(one_hot: Input[QArray], unary: Output[QArray]) -> None:
65
+ """
66
+ Conversion of one-hot encoded value to unary encoding. The output `unary` variable
67
+ is smaller in 1 qubit than the input `one_hot` variable.
68
+ For example, the state |0010> (one-hot for 2) will be converted to |110> (unary for 2).
69
+
70
+ Args:
71
+ one_hot: one-hot input array to be converted to unary encoding.
72
+ unary: unary output array.
73
+ """
74
+ inplace_one_hot_to_unary(one_hot)
75
+ lsb: QBit = QBit()
76
+ bind(one_hot, [lsb, unary])
77
+ free(lsb)
78
+
79
+
80
+ @qperm
81
+ def one_hot_to_binary(
82
+ one_hot: Input[QArray],
83
+ binary: Output[QNum[Literal["ceiling(log(one_hot.len, 2))"]]],
84
+ ) -> None:
85
+ """
86
+ Conversion of one-hot encoded value to binary encoding. The output `binary` variable
87
+ is of size log2(one_hot.size) rounded up.
88
+ For example, the state |0010> (one-hot for 2) will be converted to |01>=|2>.
89
+
90
+ Args:
91
+ one_hot: one-hot input array to be converted to binary encoding.
92
+ binary: binary output variable.
93
+ """
94
+ extension: QArray = QArray()
95
+ invert(lambda: inplace_binary_to_one_hot(one_hot))
96
+ bind(one_hot, [binary, extension])
97
+ free(extension)
98
+
99
+
100
+ @qperm
101
+ def unary_to_binary(unary: Input[QArray], binary: Output[QNum]) -> None:
102
+ """
103
+ Conversion of unary encoded value to binary encoding. The output `binary` variable
104
+ is of size log2(unary.size + 1) rounded up.
105
+ For example, the state |110> (unary for 2) will be converted to |01>=|2>.
106
+
107
+ Args:
108
+ unary: unary input array to be converted to binary encoding.
109
+ binary: binary output variable.
110
+ """
111
+ one_hot: QArray = QArray()
112
+ unary_to_one_hot(unary, one_hot)
113
+ one_hot_to_binary(one_hot, binary)
114
+
115
+
116
+ @qperm
117
+ def unary_to_one_hot(unary: Input[QArray], one_hot: Output[QArray]) -> None:
118
+ """
119
+ Conversion of unary encoded value to one-hot encoding. The output `one_hot` variable
120
+ is larger in 1 qubit than the input `unary` variable.
121
+ For example, the state |110> (unary for 2) will be converted to |0010> (one-hot for 2).
122
+
123
+ Args:
124
+ unary: unary input array to be converted to one-hot encoding.
125
+ one_hot: one-hot output array.
126
+ """
127
+ lsb: QBit = QBit()
128
+ allocate(lsb)
129
+ bind([lsb, unary], one_hot)
130
+ invert(lambda: inplace_one_hot_to_unary(one_hot))
131
+
132
+
133
+ @qperm
134
+ def binary_to_one_hot(binary: Input[QNum], one_hot: Output[QArray]) -> None:
135
+ """
136
+ Conversion of binary encoded value to one-hot encoding. The output `one_hot` variable
137
+ is of size 2^n, where n is the number of bits in the binary representation.
138
+ For example, the state |01>=|2> will be converted to |0010> (one-hot for 2).
139
+
140
+ Args:
141
+ binary: binary input variable to be converted to one-hot encoding.
142
+ one_hot: one-hot output array.
143
+ """
144
+ extension: QArray = QArray()
145
+ allocate(2**binary.size - binary.size, extension)
146
+ bind([binary, extension], one_hot)
147
+
148
+ inplace_binary_to_one_hot(one_hot)
149
+
150
+
151
+ @qperm
152
+ def binary_to_unary(binary: Input[QNum], unary: Output[QArray]) -> None:
153
+ """
154
+ Conversion of binary encoded value to unary encoding. The output `unary` variable
155
+ is of size 2^n - 1, where n is the number of bits in the binary representation.
156
+ For example, the state |01>=|2> will be converted to |110> (unary for 2).
157
+
158
+ Args:
159
+ binary: binary input variable to be converted to unary encoding.
160
+ unary: unary output array.
161
+ """
162
+ one_hot: QArray = QArray()
163
+ binary_to_one_hot(binary, one_hot)
164
+ one_hot_to_unary(one_hot, unary)
165
+
166
+
167
+ @qperm
168
+ def pad_zeros(total_size: int, qvar: Input[QArray], padded: Output[QArray]) -> None:
169
+ """
170
+ Pad the input qvar with additional qubits at the end to reach the total_size.
171
+
172
+ Args:
173
+ total_size: The desired total size after padding.
174
+ qvar: The input quantum array to be padded.
175
+ padded: The output quantum array after padding.
176
+ """
177
+ extension: QArray = QArray()
178
+ allocate(total_size - qvar.len, extension)
179
+ bind([qvar, extension], padded)
180
+
181
+
182
+ # TODO: when the functions can have default arguments, add `pad` function with direction and value
@@ -8,23 +8,21 @@ from classiq.qmod.builtins.operations import (
8
8
  power,
9
9
  within_apply,
10
10
  )
11
- from classiq.qmod.qfunc import qfunc
11
+ from classiq.qmod.qfunc import qfunc, qperm
12
12
  from classiq.qmod.qmod_parameter import CInt
13
- from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit, QNum
14
- from classiq.qmod.quantum_callable import QCallable
13
+ from classiq.qmod.qmod_variable import Const, QArray, QBit, QNum
14
+ from classiq.qmod.quantum_callable import QCallable, QPerm
15
15
  from classiq.qmod.symbolic import pi
16
16
 
17
17
 
18
- @qfunc(unchecked=["target"])
19
- def _cond_phase_flip(
20
- predicate: QCallable[Permutable[QBit]], target: Const[QBit]
21
- ) -> None:
18
+ @qperm(disable_perm_check=True, disable_const_checks=["target"])
19
+ def _cond_phase_flip(predicate: QPerm[QBit], target: Const[QBit]) -> None:
22
20
  within_apply(lambda: H(target), lambda: predicate(target))
23
21
 
24
22
 
25
- @qfunc
23
+ @qperm
26
24
  def phase_oracle(
27
- predicate: QCallable[Const[QArray[QBit]], Permutable[QBit]],
25
+ predicate: QPerm[Const[QArray[QBit]], QBit],
28
26
  target: Const[QArray[QBit]],
29
27
  ) -> None:
30
28
  """
@@ -55,7 +53,7 @@ def phase_oracle(
55
53
  )
56
54
 
57
55
 
58
- @qfunc(unchecked=["packed_vars"])
56
+ @qperm(disable_perm_check=True, disable_const_checks=["packed_vars"])
59
57
  def reflect_about_zero(packed_vars: Const[QArray[QBit]]) -> None:
60
58
  """
61
59
  [Qmod Classiq-library function]
@@ -9,6 +9,7 @@ from classiq.open_library.functions.utility_functions import switch
9
9
  from classiq.qmod.builtins.functions import IDENTITY, X, Y, Z, inplace_prepare_state
10
10
  from classiq.qmod.builtins.operations import (
11
11
  control,
12
+ if_,
12
13
  repeat,
13
14
  within_apply,
14
15
  )
@@ -16,7 +17,7 @@ from classiq.qmod.builtins.structs import IndexedPauli, SparsePauliOp
16
17
  from classiq.qmod.cparam import CArray
17
18
  from classiq.qmod.qfunc import qfunc
18
19
  from classiq.qmod.qmod_variable import QArray, QBit, QNum
19
- from classiq.qmod.quantum_callable import QCallableList
20
+ from classiq.qmod.quantum_callable import QCallable, QCallableList
20
21
 
21
22
 
22
23
  @qfunc
@@ -36,27 +37,23 @@ def apply_pauli_term(pauli_string: CArray[IndexedPauli], x: QArray[QBit]) -> Non
36
37
 
37
38
 
38
39
  @qfunc
39
- def lcu(
40
+ def prepare_select(
40
41
  coefficients: list[float],
41
- unitaries: QCallableList,
42
+ select: QCallable[QNum],
42
43
  block: QNum[Literal["max(ceiling(log(coefficients.len, 2)), 1)"]],
43
44
  ) -> None:
44
45
  """
45
46
  [Qmod Classiq-library function]
46
47
 
47
- Implements a general linear combination of unitaries (LCU) procedure. The algorithm prepares a superposition
48
- over the `unitaries` according to `magnitudes`, and then conditionally applies each unitary controlled by the `block`.
49
-
50
- The operation is of the form:
51
-
52
- $$\\sum_j \\alpha_j U_j$$
53
-
54
- where $U_j$ is a unitary operation applied to `data`.
48
+ Applies the 'Prepare-Select' scheme used for Linear Combination of Unitaries (LCU).
49
+ Compared to the `lcu` function, here the Select operator should be provided directly, allowing to take advantage of some structure for
50
+ the unitaries of the LCU.
51
+ The select operator is defined by: $\\mathrm{SELECT} = \\sum_{j=0}^{m-1} |j\rangle\\!\\langle j|_{block} \\otimes U_j$.
55
52
 
56
53
  Args:
57
54
  coefficients: L1-normalized array of $\\{ \\alpha_j \\}$ of the LCU coefficients.
58
- unitaries: A list of quantum callable functions to be applied conditionally.
59
- block: Quantum variable that holds the superposition index used for conditional application of each unitary.
55
+ select: A quantum callable to be applied between the state preparation and its inverse. Its input is the `block` variable, labeling the index of the unitaries in the LCU.
56
+ block: A Quantum variable that holds the index used as input for the 'select' operator.
60
57
  """
61
58
  coefficients = coefficients + [0] * (
62
59
  2**block.size - len(coefficients) # type:ignore[operator]
@@ -68,16 +65,48 @@ def lcu(
68
65
  within_apply(
69
66
  lambda: inplace_prepare_state(magnitudes, 0, block),
70
67
  lambda: [
71
- repeat(
72
- count=unitaries.len,
73
- iteration=lambda i: control(block == i, lambda: unitaries[i]()),
68
+ select(block),
69
+ if_(
70
+ not np.allclose(np.array(phases) % (2 * np.pi), 0),
71
+ lambda: apply_phase_table(phases, block),
74
72
  ),
75
- # TODO: replace to sparse constant phase
76
- apply_phase_table(phases, block),
77
73
  ],
78
74
  )
79
75
 
80
76
 
77
+ @qfunc
78
+ def lcu(
79
+ coefficients: list[float],
80
+ unitaries: QCallableList,
81
+ block: QNum[Literal["max(ceiling(log(coefficients.len, 2)), 1)"]],
82
+ ) -> None:
83
+ """
84
+ [Qmod Classiq-library function]
85
+
86
+ Implements a general linear combination of unitaries (LCU) procedure. The algorithm prepares a superposition
87
+ over the `unitaries` according to the given `coefficients`, and then conditionally applies each unitary controlled by the `block`.
88
+
89
+ The operation is of the form:
90
+
91
+ $$\\sum_j \\alpha_j U_j$$
92
+
93
+ where $U_j$ is a unitary operation applied to `data`.
94
+
95
+ Args:
96
+ coefficients: L1-normalized array of $\\{ \\alpha_j \\}$ of the LCU coefficients.
97
+ unitaries: A list of quantum callable functions to be applied conditionally.
98
+ block: Quantum variable that holds the superposition index used for conditional application of each unitary.
99
+ """
100
+ prepare_select(
101
+ coefficients,
102
+ lambda _block: repeat(
103
+ count=unitaries.len,
104
+ iteration=lambda i: control(_block == i, lambda: unitaries[i]()),
105
+ ),
106
+ block,
107
+ )
108
+
109
+
81
110
  @qfunc
82
111
  def lcu_pauli(
83
112
  operator: SparsePauliOp,
@@ -8,11 +8,12 @@ from classiq.qmod.builtins.operations import (
8
8
  control,
9
9
  invert,
10
10
  repeat,
11
+ skip_control,
11
12
  within_apply,
12
13
  )
13
14
  from classiq.qmod.cparam import CInt
14
- from classiq.qmod.qfunc import qfunc
15
- from classiq.qmod.qmod_variable import Const, Permutable, QArray, QBit
15
+ from classiq.qmod.qfunc import qfunc, qperm
16
+ from classiq.qmod.qmod_variable import Const, QArray, QBit
16
17
  from classiq.qmod.symbolic import min, mod_inverse
17
18
 
18
19
 
@@ -51,9 +52,9 @@ def qft_space_add_const(value: CInt, phi_b: QArray[QBit]) -> None:
51
52
  )
52
53
 
53
54
 
54
- @qfunc(unchecked=["phi_b"])
55
+ @qperm(disable_perm_check=True)
55
56
  def cc_modular_add(
56
- n: CInt, a: CInt, phi_b: Permutable[QArray[QBit]], c1: Const[QBit], c2: Const[QBit]
57
+ n: CInt, a: CInt, phi_b: QArray[QBit], c1: Const[QBit], c2: Const[QBit]
57
58
  ) -> None:
58
59
  """
59
60
  [Qmod Classiq-library function]
@@ -91,11 +92,11 @@ def cc_modular_add(
91
92
  free(aux)
92
93
 
93
94
 
94
- @qfunc(unchecked=["b"])
95
+ @qperm(disable_perm_check=True)
95
96
  def c_modular_multiply(
96
97
  n: CInt,
97
98
  a: CInt,
98
- b: Permutable[QArray[QBit]],
99
+ b: QArray[QBit],
99
100
  x: Const[QArray[QBit]],
100
101
  ctrl: Const[QBit],
101
102
  ) -> None:
@@ -123,8 +124,8 @@ def c_modular_multiply(
123
124
  )
124
125
 
125
126
 
126
- @qfunc
127
- def multiswap(x: Permutable[QArray[QBit]], y: Permutable[QArray[QBit]]) -> None:
127
+ @qperm
128
+ def multiswap(x: QArray[QBit], y: QArray[QBit]) -> None:
128
129
  """
129
130
  [Qmod Classiq-library function]
130
131
 
@@ -164,6 +165,90 @@ def inplace_c_modular_multiply(n: CInt, a: CInt, x: QArray[QBit], ctrl: QBit) ->
164
165
  free(b)
165
166
 
166
167
 
168
+ @qperm(disable_perm_check=True)
169
+ def modular_add_qft_space(n: CInt, a: CInt, phi_b: QArray[QBit]) -> None:
170
+ """
171
+ [Qmod Classiq-library function]
172
+
173
+ Adds a constant `a` to a quantum number `phi_b` modulo the constant `n`.
174
+ The quantum number `phi_b` is assumed to be in the QFT space.
175
+
176
+ Args:
177
+ n: The modulo number.
178
+ a: The constant to add to the quantum number.
179
+ phi_b: The quantum number to which the constant is added.
180
+
181
+ """
182
+ aux = QBit()
183
+
184
+ allocate(aux)
185
+ qft_space_add_const(a, phi_b),
186
+ skip_control(
187
+ lambda: (
188
+ invert(lambda: qft_space_add_const(n, phi_b)),
189
+ _check_msb(1, phi_b, aux),
190
+ control(aux, lambda: qft_space_add_const(n, phi_b)),
191
+ )
192
+ )
193
+ invert(lambda: qft_space_add_const(a, phi_b))
194
+ skip_control(lambda: _check_msb(0, phi_b, aux))
195
+ qft_space_add_const(a, phi_b)
196
+ free(aux)
197
+
198
+
199
+ @qperm(disable_perm_check=True)
200
+ def modular_multiply(
201
+ n: CInt,
202
+ a: CInt,
203
+ b: QArray[QBit],
204
+ x: Const[QArray[QBit]],
205
+ ) -> None:
206
+ """
207
+ [Qmod Classiq-library function]
208
+
209
+ Performs out-of-place multiplication of a quantum number `x` by a classical number `a` modulo classical number `n`,
210
+ and adds the result to a quantum array `b` (Applies $b += xa \\mod n$).
211
+
212
+ Args:
213
+ n: The modulo number. Should be non-negative.
214
+ a: The classical factor. Should be non-negative.
215
+ b: The quantum number added to the multiplication result. Stores the result of the multiplication.
216
+ x: The quantum factor.
217
+ """
218
+ within_apply(
219
+ lambda: qft(b),
220
+ lambda: repeat(
221
+ count=x.len,
222
+ iteration=lambda index: control(
223
+ x[index], lambda: modular_add_qft_space(n, (a * (2**index)) % n, b)
224
+ ),
225
+ ),
226
+ )
227
+
228
+
229
+ @qfunc
230
+ def inplace_modular_multiply(n: CInt, a: CInt, x: QArray[QBit]) -> None:
231
+ """
232
+ [Qmod Classiq-library function]
233
+
234
+ Performs multiplication of a quantum number `x` by a classical number `a` modulo classical number `n`
235
+ (Applies $x=xa \\mod n$).
236
+
237
+ Args:
238
+ n: The modulo number. Should be non-negative.
239
+ a: The classical factor. Should be non-negative.
240
+ x: The quantum factor.
241
+
242
+ Comment: It is assumed that `a` has an inverse modulo `n`
243
+ """
244
+ b: QArray[QBit] = QArray(length=x.len + 1)
245
+ allocate(b)
246
+ modular_multiply(n, a, b, x)
247
+ multiswap(x, b)
248
+ invert(lambda: modular_multiply(n, mod_inverse(a, n), b, x))
249
+ free(b)
250
+
251
+
167
252
  @qfunc
168
253
  def modular_exp(n: CInt, a: CInt, x: QArray[QBit], power: QArray[QBit]) -> None:
169
254
  """