classiq 0.37.1__py3-none-any.whl → 0.65.3__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 (516) hide show
  1. classiq/__init__.py +49 -34
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +3 -2
  3. classiq/_analyzer_extras/interactive_hardware.py +3 -3
  4. classiq/_internals/api_wrapper.py +241 -95
  5. classiq/_internals/async_utils.py +2 -77
  6. classiq/_internals/authentication/auth0.py +26 -10
  7. classiq/_internals/authentication/authentication.py +11 -0
  8. classiq/_internals/authentication/device.py +18 -8
  9. classiq/_internals/authentication/password_manager.py +40 -13
  10. classiq/_internals/authentication/token_manager.py +11 -6
  11. classiq/_internals/client.py +106 -37
  12. classiq/_internals/config.py +3 -4
  13. classiq/_internals/host_checker.py +38 -15
  14. classiq/_internals/jobs.py +56 -50
  15. classiq/_internals/type_validation.py +9 -9
  16. classiq/analyzer/__init__.py +1 -3
  17. classiq/analyzer/analyzer.py +50 -47
  18. classiq/analyzer/analyzer_utilities.py +15 -15
  19. classiq/analyzer/rb.py +19 -20
  20. classiq/analyzer/show_interactive_hack.py +30 -7
  21. classiq/analyzer/url_utils.py +2 -3
  22. classiq/applications/__init__.py +3 -12
  23. classiq/applications/chemistry/__init__.py +14 -10
  24. classiq/applications/chemistry/ansatz_parameters.py +4 -4
  25. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +170 -170
  26. classiq/applications/chemistry/ground_state_problem.py +1 -1
  27. classiq/applications/combinatorial_helpers/allowed_constraints.py +23 -0
  28. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
  29. classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
  30. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +166 -0
  31. classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
  32. classiq/applications/combinatorial_helpers/encoding_utils.py +124 -0
  33. classiq/applications/combinatorial_helpers/memory.py +75 -0
  34. classiq/applications/combinatorial_helpers/optimization_model.py +193 -0
  35. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
  36. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
  37. classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
  38. classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
  39. classiq/applications/combinatorial_helpers/transformations/encoding.py +189 -0
  40. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +143 -0
  41. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +120 -0
  42. classiq/applications/combinatorial_helpers/transformations/penalty.py +31 -0
  43. classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
  44. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +74 -0
  45. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +87 -0
  46. classiq/applications/combinatorial_optimization/__init__.py +24 -5
  47. classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
  48. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +137 -0
  49. classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
  50. classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
  51. classiq/applications/finance/__init__.py +4 -5
  52. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +50 -57
  53. classiq/applications/grover/__init__.py +9 -0
  54. classiq/applications/grover/grover_model_constructor.py +157 -0
  55. classiq/applications/hamiltonian/__init__.py +0 -0
  56. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  57. classiq/applications/libraries/__init__.py +0 -0
  58. classiq/applications/libraries/qmci_library.py +22 -0
  59. classiq/applications/qnn/__init__.py +2 -4
  60. classiq/applications/qnn/circuit_utils.py +8 -8
  61. classiq/applications/qnn/datasets/__init__.py +9 -11
  62. classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
  63. classiq/applications/qnn/datasets/dataset_not.py +2 -1
  64. classiq/applications/qnn/datasets/dataset_parity.py +2 -2
  65. classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
  66. classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
  67. classiq/applications/qnn/qlayer.py +30 -10
  68. classiq/applications/qnn/torch_utils.py +4 -3
  69. classiq/applications/qnn/types.py +7 -7
  70. classiq/applications/qsvm/__init__.py +6 -4
  71. classiq/applications/qsvm/qsvm.py +4 -10
  72. classiq/applications/qsvm/qsvm_data_generation.py +5 -8
  73. classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
  74. classiq/execution/__init__.py +8 -3
  75. classiq/execution/all_hardware_devices.py +11 -0
  76. classiq/execution/execution_session.py +400 -0
  77. classiq/execution/iqcc.py +63 -0
  78. classiq/execution/jobs.py +197 -25
  79. classiq/execution/qnn.py +79 -0
  80. classiq/executor.py +23 -117
  81. classiq/interface/_version.py +1 -1
  82. classiq/interface/analyzer/analysis_params.py +49 -16
  83. classiq/interface/analyzer/cytoscape_graph.py +15 -9
  84. classiq/interface/analyzer/result.py +36 -32
  85. classiq/interface/applications/qsvm.py +28 -25
  86. classiq/interface/ast_node.py +16 -0
  87. classiq/interface/backend/backend_preferences.py +390 -119
  88. classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
  89. classiq/interface/backend/pydantic_backend.py +27 -22
  90. classiq/interface/backend/quantum_backend_providers.py +70 -16
  91. classiq/interface/chemistry/fermionic_operator.py +43 -32
  92. classiq/interface/chemistry/ground_state_problem.py +42 -24
  93. classiq/interface/chemistry/molecule.py +20 -14
  94. classiq/interface/chemistry/operator.py +75 -236
  95. classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
  96. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +2 -4
  97. classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
  98. classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
  99. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
  100. classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
  101. classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
  102. classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
  103. classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
  104. classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
  105. classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
  106. classiq/interface/combinatorial_optimization/examples/set_cover.py +3 -3
  107. classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
  108. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
  109. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +14 -9
  110. classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
  111. classiq/interface/combinatorial_optimization/result.py +1 -3
  112. classiq/interface/combinatorial_optimization/solver_types.py +1 -1
  113. classiq/interface/debug_info/__init__.py +0 -0
  114. classiq/interface/debug_info/debug_info.py +86 -0
  115. classiq/interface/exceptions.py +201 -0
  116. classiq/interface/execution/iqcc.py +19 -0
  117. classiq/interface/execution/jobs.py +15 -12
  118. classiq/interface/execution/primitives.py +18 -0
  119. classiq/interface/executor/constants.py +1 -0
  120. classiq/interface/executor/estimation.py +2 -2
  121. classiq/interface/executor/execution_preferences.py +26 -143
  122. classiq/interface/executor/execution_request.py +36 -56
  123. classiq/interface/executor/execution_result.py +30 -8
  124. classiq/interface/executor/iqae_result.py +4 -6
  125. classiq/interface/executor/optimizer_preferences.py +34 -22
  126. classiq/interface/executor/{quantum_program.py → quantum_code.py} +44 -34
  127. classiq/interface/executor/quantum_instruction_set.py +3 -2
  128. classiq/interface/executor/register_initialization.py +12 -17
  129. classiq/interface/executor/result.py +122 -64
  130. classiq/interface/executor/vqe_result.py +11 -11
  131. classiq/interface/finance/function_input.py +42 -19
  132. classiq/interface/finance/gaussian_model_input.py +7 -5
  133. classiq/interface/finance/log_normal_model_input.py +6 -4
  134. classiq/interface/finance/model_input.py +6 -4
  135. classiq/interface/generator/adjacency.py +1 -3
  136. classiq/interface/generator/amplitude_loading.py +27 -14
  137. classiq/interface/generator/ansatz_library.py +5 -5
  138. classiq/interface/generator/application_apis/__init__.py +1 -0
  139. classiq/interface/generator/application_apis/arithmetic_declarations.py +17 -0
  140. classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
  141. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
  142. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  143. classiq/interface/generator/application_apis/finance_declarations.py +48 -69
  144. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
  145. classiq/interface/generator/arith/argument_utils.py +57 -6
  146. classiq/interface/generator/arith/arithmetic.py +37 -16
  147. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +15 -17
  148. classiq/interface/generator/arith/arithmetic_expression_abc.py +70 -26
  149. classiq/interface/generator/arith/arithmetic_expression_parser.py +18 -12
  150. classiq/interface/generator/arith/arithmetic_expression_validator.py +61 -43
  151. classiq/interface/generator/arith/arithmetic_operations.py +19 -16
  152. classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
  153. classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
  154. classiq/interface/generator/arith/ast_node_rewrite.py +4 -3
  155. classiq/interface/generator/arith/binary_ops.py +375 -139
  156. classiq/interface/generator/arith/endianness.py +1 -1
  157. classiq/interface/generator/arith/extremum_operations.py +96 -23
  158. classiq/interface/generator/arith/logical_ops.py +16 -12
  159. classiq/interface/generator/arith/machine_precision.py +3 -0
  160. classiq/interface/generator/arith/number_utils.py +44 -48
  161. classiq/interface/generator/arith/register_user_input.py +70 -27
  162. classiq/interface/generator/arith/unary_ops.py +57 -46
  163. classiq/interface/generator/arith/uncomputation_methods.py +1 -1
  164. classiq/interface/generator/builtin_api_builder.py +2 -9
  165. classiq/interface/generator/chemistry_function_params.py +5 -5
  166. classiq/interface/generator/circuit_code/circuit_code.py +7 -7
  167. classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
  168. classiq/interface/generator/commuting_pauli_exponentiation.py +8 -6
  169. classiq/interface/generator/compiler_keywords.py +8 -0
  170. classiq/interface/generator/complex_type.py +13 -25
  171. classiq/interface/generator/constant.py +3 -4
  172. classiq/interface/generator/control_state.py +35 -28
  173. classiq/interface/generator/copy.py +47 -0
  174. classiq/interface/generator/custom_ansatz.py +2 -5
  175. classiq/interface/generator/distance.py +3 -5
  176. classiq/interface/generator/excitations.py +3 -2
  177. classiq/interface/generator/expressions/atomic_expression_functions.py +26 -8
  178. classiq/interface/generator/expressions/enums/__init__.py +0 -10
  179. classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
  180. classiq/interface/generator/expressions/evaluated_expression.py +21 -7
  181. classiq/interface/generator/expressions/expression.py +27 -15
  182. classiq/interface/generator/expressions/expression_constants.py +9 -3
  183. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  184. classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
  185. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +59 -0
  186. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
  187. classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
  188. classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
  189. classiq/interface/generator/expressions/sympy_supported_expressions.py +20 -11
  190. classiq/interface/generator/finance.py +3 -3
  191. classiq/interface/generator/function_param_library.py +6 -6
  192. classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
  193. classiq/interface/generator/function_params.py +42 -69
  194. classiq/interface/generator/functions/__init__.py +0 -22
  195. classiq/interface/generator/functions/builtins/__init__.py +0 -0
  196. classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
  197. classiq/interface/generator/functions/classical_function_declaration.py +18 -9
  198. classiq/interface/generator/functions/classical_type.py +47 -166
  199. classiq/interface/generator/functions/concrete_types.py +55 -0
  200. classiq/interface/generator/functions/function_declaration.py +13 -14
  201. classiq/interface/generator/functions/port_declaration.py +1 -13
  202. classiq/interface/generator/functions/qmod_python_interface.py +2 -1
  203. classiq/interface/generator/functions/type_name.py +90 -0
  204. classiq/interface/generator/generated_circuit_data.py +155 -22
  205. classiq/interface/generator/grover_diffuser.py +32 -25
  206. classiq/interface/generator/grover_operator.py +34 -23
  207. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
  208. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  209. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +12 -8
  210. classiq/interface/generator/hardware/hardware_data.py +76 -36
  211. classiq/interface/generator/hardware_efficient_ansatz.py +38 -17
  212. classiq/interface/generator/hartree_fock.py +14 -4
  213. classiq/interface/generator/identity.py +10 -6
  214. classiq/interface/generator/linear_pauli_rotations.py +33 -19
  215. classiq/interface/generator/mcmt_method.py +1 -1
  216. classiq/interface/generator/mcu.py +20 -16
  217. classiq/interface/generator/mcx.py +29 -20
  218. classiq/interface/generator/model/__init__.py +2 -5
  219. classiq/interface/generator/model/constraints.py +27 -8
  220. classiq/interface/generator/model/model.py +32 -203
  221. classiq/interface/generator/model/preferences/preferences.py +118 -43
  222. classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +27 -22
  223. classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
  224. classiq/interface/generator/oracles/custom_oracle.py +17 -13
  225. classiq/interface/generator/oracles/oracle_abc.py +9 -9
  226. classiq/interface/generator/partitioned_register.py +7 -7
  227. classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
  228. classiq/interface/generator/preferences/optimization.py +1 -2
  229. classiq/interface/generator/qpe.py +47 -34
  230. classiq/interface/generator/qsvm.py +13 -17
  231. classiq/interface/generator/quantum_function_call.py +107 -87
  232. classiq/interface/generator/{generated_circuit.py → quantum_program.py} +50 -37
  233. classiq/interface/generator/range_types.py +13 -12
  234. classiq/interface/generator/register_role.py +18 -6
  235. classiq/interface/generator/slice_parsing_utils.py +11 -6
  236. classiq/interface/generator/standard_gates/controlled_standard_gates.py +32 -39
  237. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  238. classiq/interface/generator/standard_gates/standard_gates.py +3 -3
  239. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  240. classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
  241. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  242. classiq/interface/generator/state_preparation/distributions.py +16 -15
  243. classiq/interface/generator/state_preparation/metrics.py +5 -7
  244. classiq/interface/generator/state_preparation/state_preparation.py +30 -23
  245. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  246. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
  247. classiq/interface/generator/transpiler_basis_gates.py +7 -3
  248. classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
  249. classiq/interface/generator/types/compilation_metadata.py +6 -0
  250. classiq/interface/generator/types/enum_declaration.py +54 -0
  251. classiq/interface/generator/types/qstruct_declaration.py +18 -0
  252. classiq/interface/generator/types/struct_declaration.py +15 -14
  253. classiq/interface/generator/ucc.py +9 -6
  254. classiq/interface/generator/unitary_gate.py +10 -6
  255. classiq/interface/generator/user_defined_function_params.py +4 -1
  256. classiq/interface/generator/validations/flow_graph.py +11 -9
  257. classiq/interface/generator/validations/validator_functions.py +8 -6
  258. classiq/interface/generator/visitor.py +23 -16
  259. classiq/interface/hardware.py +31 -10
  260. classiq/interface/helpers/classproperty.py +8 -0
  261. classiq/interface/helpers/custom_encoders.py +3 -0
  262. classiq/interface/helpers/custom_pydantic_types.py +40 -50
  263. classiq/interface/helpers/datastructures.py +26 -0
  264. classiq/interface/helpers/hashable_mixin.py +3 -2
  265. classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
  266. classiq/interface/helpers/pydantic_model_helpers.py +7 -11
  267. classiq/interface/helpers/validation_helpers.py +4 -21
  268. classiq/interface/helpers/versioned_model.py +1 -1
  269. classiq/interface/ide/ide_data.py +16 -20
  270. classiq/interface/ide/visual_model.py +130 -0
  271. classiq/interface/interface_version.py +1 -0
  272. classiq/interface/jobs.py +35 -6
  273. classiq/interface/model/allocate.py +16 -0
  274. classiq/interface/model/bind_operation.py +44 -14
  275. classiq/interface/model/classical_if.py +15 -0
  276. classiq/interface/model/classical_parameter_declaration.py +33 -3
  277. classiq/interface/model/control.py +45 -0
  278. classiq/interface/model/handle_binding.py +298 -20
  279. classiq/interface/model/inplace_binary_operation.py +31 -26
  280. classiq/interface/model/invert.py +12 -0
  281. classiq/interface/model/model.py +87 -73
  282. classiq/interface/model/native_function_definition.py +16 -21
  283. classiq/interface/model/parameter.py +13 -0
  284. classiq/interface/model/phase_operation.py +11 -0
  285. classiq/interface/model/port_declaration.py +27 -9
  286. classiq/interface/model/power.py +14 -0
  287. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +38 -21
  288. classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
  289. classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
  290. classiq/interface/model/quantum_function_call.py +146 -462
  291. classiq/interface/model/quantum_function_declaration.py +193 -152
  292. classiq/interface/model/quantum_lambda_function.py +65 -0
  293. classiq/interface/model/quantum_statement.py +71 -12
  294. classiq/interface/model/quantum_type.py +205 -67
  295. classiq/interface/model/quantum_variable_declaration.py +4 -26
  296. classiq/interface/model/repeat.py +15 -0
  297. classiq/interface/model/statement_block.py +58 -0
  298. classiq/interface/model/validation_handle.py +13 -6
  299. classiq/interface/model/variable_declaration_statement.py +3 -1
  300. classiq/interface/model/within_apply_operation.py +13 -0
  301. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
  302. classiq/interface/server/global_versions.py +6 -7
  303. classiq/interface/server/routes.py +22 -21
  304. classiq/interface/source_reference.py +59 -0
  305. classiq/model_expansions/__init__.py +0 -0
  306. classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
  307. classiq/model_expansions/capturing/__init__.py +0 -0
  308. classiq/model_expansions/capturing/captured_vars.py +435 -0
  309. classiq/model_expansions/capturing/mangling_utils.py +56 -0
  310. classiq/model_expansions/closure.py +171 -0
  311. classiq/model_expansions/debug_flag.py +3 -0
  312. classiq/model_expansions/evaluators/__init__.py +0 -0
  313. classiq/model_expansions/evaluators/arg_type_match.py +158 -0
  314. classiq/model_expansions/evaluators/argument_types.py +42 -0
  315. classiq/model_expansions/evaluators/classical_expression.py +36 -0
  316. classiq/model_expansions/evaluators/control.py +144 -0
  317. classiq/model_expansions/evaluators/parameter_types.py +226 -0
  318. classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
  319. classiq/model_expansions/evaluators/type_type_match.py +90 -0
  320. classiq/model_expansions/expression_evaluator.py +135 -0
  321. classiq/model_expansions/expression_renamer.py +76 -0
  322. classiq/model_expansions/function_builder.py +247 -0
  323. classiq/model_expansions/generative_functions.py +158 -0
  324. classiq/model_expansions/interpreters/__init__.py +0 -0
  325. classiq/model_expansions/interpreters/base_interpreter.py +263 -0
  326. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
  327. classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
  328. classiq/model_expansions/model_tables.py +18 -0
  329. classiq/model_expansions/quantum_operations/__init__.py +9 -0
  330. classiq/model_expansions/quantum_operations/bind.py +60 -0
  331. classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
  332. classiq/model_expansions/quantum_operations/classicalif.py +53 -0
  333. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
  334. classiq/model_expansions/quantum_operations/emitter.py +181 -0
  335. classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
  336. classiq/model_expansions/quantum_operations/repeat.py +56 -0
  337. classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
  338. classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
  339. classiq/model_expansions/scope.py +240 -0
  340. classiq/model_expansions/scope_initialization.py +150 -0
  341. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  342. classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
  343. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
  344. classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
  345. classiq/model_expansions/transformers/__init__.py +0 -0
  346. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  347. classiq/model_expansions/transformers/var_splitter.py +299 -0
  348. classiq/model_expansions/utils/__init__.py +0 -0
  349. classiq/model_expansions/utils/counted_name_allocator.py +11 -0
  350. classiq/model_expansions/utils/handles_collector.py +33 -0
  351. classiq/model_expansions/visitors/__init__.py +0 -0
  352. classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
  353. classiq/model_expansions/visitors/variable_references.py +144 -0
  354. classiq/open_library/__init__.py +4 -0
  355. classiq/open_library/functions/__init__.py +130 -0
  356. classiq/open_library/functions/amplitude_estimation.py +30 -0
  357. classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
  358. classiq/open_library/functions/grover.py +157 -0
  359. classiq/open_library/functions/hea.py +115 -0
  360. classiq/open_library/functions/linear_pauli_rotation.py +82 -0
  361. classiq/open_library/functions/modular_exponentiation.py +201 -0
  362. classiq/open_library/functions/qaoa_penalty.py +117 -0
  363. classiq/open_library/functions/qft_functions.py +54 -0
  364. classiq/open_library/functions/qpe.py +46 -0
  365. classiq/open_library/functions/qsvt.py +331 -0
  366. classiq/open_library/functions/state_preparation.py +301 -0
  367. classiq/open_library/functions/swap_test.py +27 -0
  368. classiq/open_library/functions/utility_functions.py +81 -0
  369. classiq/open_library/functions/variational.py +52 -0
  370. classiq/qmod/__init__.py +17 -10
  371. classiq/qmod/builtins/__init__.py +19 -2
  372. classiq/qmod/builtins/classical_execution_primitives.py +60 -47
  373. classiq/qmod/builtins/classical_functions.py +44 -38
  374. classiq/qmod/builtins/constants.py +10 -0
  375. classiq/qmod/builtins/enums.py +208 -0
  376. classiq/qmod/builtins/functions/__init__.py +137 -0
  377. classiq/qmod/builtins/functions/allocation.py +150 -0
  378. classiq/qmod/builtins/functions/arithmetic.py +55 -0
  379. classiq/qmod/builtins/functions/benchmarking.py +8 -0
  380. classiq/qmod/builtins/functions/chemistry.py +91 -0
  381. classiq/qmod/builtins/functions/exponentiation.py +105 -0
  382. classiq/qmod/builtins/functions/finance.py +34 -0
  383. classiq/qmod/builtins/functions/operators.py +16 -0
  384. classiq/qmod/builtins/functions/qsvm.py +24 -0
  385. classiq/qmod/builtins/functions/standard_gates.py +651 -0
  386. classiq/qmod/builtins/operations.py +379 -57
  387. classiq/qmod/builtins/structs.py +103 -80
  388. classiq/qmod/cfunc.py +42 -0
  389. classiq/qmod/classical_function.py +8 -20
  390. classiq/qmod/cparam.py +64 -0
  391. classiq/qmod/create_model_function.py +56 -0
  392. classiq/qmod/declaration_inferrer.py +145 -112
  393. classiq/qmod/expression_query.py +39 -0
  394. classiq/qmod/generative.py +42 -0
  395. classiq/qmod/model_state_container.py +19 -5
  396. classiq/qmod/native/__init__.py +7 -0
  397. classiq/qmod/native/expression_to_qmod.py +194 -0
  398. classiq/qmod/native/pretty_printer.py +401 -0
  399. classiq/qmod/pretty_print/__init__.py +7 -0
  400. classiq/qmod/pretty_print/expression_to_python.py +222 -0
  401. classiq/qmod/pretty_print/pretty_printer.py +572 -0
  402. classiq/qmod/python_classical_type.py +67 -0
  403. classiq/qmod/qfunc.py +79 -0
  404. classiq/qmod/qmod_constant.py +143 -0
  405. classiq/qmod/qmod_parameter.py +84 -53
  406. classiq/qmod/qmod_variable.py +497 -100
  407. classiq/qmod/quantum_callable.py +17 -7
  408. classiq/qmod/quantum_expandable.py +278 -105
  409. classiq/qmod/quantum_function.py +232 -48
  410. classiq/qmod/semantics/__init__.py +0 -0
  411. classiq/qmod/semantics/annotation/__init__.py +0 -0
  412. classiq/qmod/semantics/annotation/call_annotation.py +92 -0
  413. classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
  414. classiq/qmod/semantics/error_manager.py +88 -0
  415. classiq/qmod/semantics/lambdas.py +25 -0
  416. classiq/qmod/semantics/static_semantics_visitor.py +384 -0
  417. classiq/qmod/semantics/validation/__init__.py +0 -0
  418. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  419. classiq/qmod/semantics/validation/func_call_validation.py +99 -0
  420. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  421. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  422. classiq/qmod/semantics/validation/main_validation.py +33 -0
  423. classiq/qmod/semantics/validation/types_validation.py +128 -0
  424. classiq/qmod/symbolic.py +178 -111
  425. classiq/qmod/symbolic_expr.py +36 -12
  426. classiq/qmod/symbolic_type.py +2 -5
  427. classiq/qmod/type_attribute_remover.py +32 -0
  428. classiq/qmod/utilities.py +108 -1
  429. classiq/qmod/write_qmod.py +53 -0
  430. classiq/synthesis.py +210 -22
  431. {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -8
  432. classiq-0.65.3.dist-info/RECORD +521 -0
  433. {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/WHEEL +1 -1
  434. classiq/_internals/_qfunc_ext.py +0 -6
  435. classiq/applications/benchmarking/__init__.py +0 -9
  436. classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
  437. classiq/applications/numpy_utils.py +0 -37
  438. classiq/applications_model_constructors/__init__.py +0 -17
  439. classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
  440. classiq/applications_model_constructors/grover_model_constructor.py +0 -227
  441. classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
  442. classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
  443. classiq/builtin_functions/__init__.py +0 -43
  444. classiq/builtin_functions/amplitude_loading.py +0 -3
  445. classiq/builtin_functions/binary_ops.py +0 -1
  446. classiq/builtin_functions/exponentiation.py +0 -5
  447. classiq/builtin_functions/qpe.py +0 -4
  448. classiq/builtin_functions/qsvm.py +0 -7
  449. classiq/builtin_functions/range_types.py +0 -5
  450. classiq/builtin_functions/standard_gates.py +0 -1
  451. classiq/builtin_functions/state_preparation.py +0 -6
  452. classiq/builtin_functions/suzuki_trotter.py +0 -3
  453. classiq/exceptions.py +0 -131
  454. classiq/interface/executor/aws_execution_cost.py +0 -72
  455. classiq/interface/executor/error_mitigation.py +0 -6
  456. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -115
  457. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -59
  458. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  459. classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
  460. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
  461. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  462. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  463. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  464. classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
  465. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  466. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
  467. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
  468. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -862
  469. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
  470. classiq/interface/generator/functions/foreign_function_definition.py +0 -106
  471. classiq/interface/generator/functions/function_implementation.py +0 -103
  472. classiq/interface/generator/functions/native_function_definition.py +0 -153
  473. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  474. classiq/interface/generator/functions/register.py +0 -42
  475. classiq/interface/generator/functions/register_mapping_data.py +0 -102
  476. classiq/interface/generator/inequality_mixer.py +0 -51
  477. classiq/interface/generator/model/classical_main_validator.py +0 -106
  478. classiq/interface/generator/range_mixer.py +0 -56
  479. classiq/interface/generator/state_propagator.py +0 -63
  480. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -2
  481. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
  482. classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
  483. classiq/interface/generator/types/combinatorial_problem.py +0 -26
  484. classiq/interface/ide/show.py +0 -34
  485. classiq/interface/model/common_model_types.py +0 -23
  486. classiq/interface/model/numeric_reinterpretation.py +0 -25
  487. classiq/interface/model/operator_synthesis_data.py +0 -48
  488. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  489. classiq/interface/model/quantum_if_operation.py +0 -95
  490. classiq/interface/model/resolvers/function_call_resolver.py +0 -43
  491. classiq/interface/model/validations/handle_validation_base.py +0 -55
  492. classiq/interface/model/validations/handles_validator.py +0 -154
  493. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  494. classiq/model/__init__.py +0 -14
  495. classiq/model/composite_function_generator.py +0 -33
  496. classiq/model/function_handler.py +0 -466
  497. classiq/model/function_handler.pyi +0 -152
  498. classiq/model/logic_flow.py +0 -149
  499. classiq/model/logic_flow_change_handler.py +0 -71
  500. classiq/model/model.py +0 -246
  501. classiq/qmod/builtins/functions.py +0 -896
  502. classiq/qmod/qmod_struct.py +0 -37
  503. classiq/quantum_functions/__init__.py +0 -17
  504. classiq/quantum_functions/annotation_parser.py +0 -207
  505. classiq/quantum_functions/decorators.py +0 -22
  506. classiq/quantum_functions/function_library.py +0 -181
  507. classiq/quantum_functions/function_parser.py +0 -74
  508. classiq/quantum_functions/quantum_function.py +0 -236
  509. classiq-0.37.1.dist-info/RECORD +0 -418
  510. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
  511. /classiq/{interface/generator/credit_risk_example → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
  512. /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/pauli_helpers}/__init__.py +0 -0
  513. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/py.typed} +0 -0
  514. /classiq/{interface/model/resolvers → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  515. /classiq/{interface/model/validations → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  516. /classiq/{_internals → interface}/enum_utils.py +0 -0
@@ -1,21 +1,21 @@
1
- from typing import Any, Dict, List, Tuple
1
+ from typing import Any
2
2
 
3
3
  from classiq.interface.applications.qsvm import DataList, LabelsInt
4
- from classiq.interface.generator.expressions.enums.pauli import Pauli
5
- from classiq.interface.generator.expressions.enums.qsvm_feature_map_entanglement import (
6
- QSVMFeatureMapEntanglement,
7
- )
4
+ from classiq.interface.exceptions import ClassiqValueError
8
5
  from classiq.interface.generator.expressions.expression import Expression
9
6
  from classiq.interface.generator.functions.port_declaration import (
10
7
  PortDeclarationDirection,
11
8
  )
9
+ from classiq.interface.model.allocate import Allocate
12
10
  from classiq.interface.model.handle_binding import HandleBinding
13
11
  from classiq.interface.model.model import Model, SerializedModel
14
12
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
15
13
  from classiq.interface.model.port_declaration import PortDeclaration
16
14
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
15
+ from classiq.interface.model.quantum_statement import QuantumStatement
17
16
 
18
- from classiq.exceptions import ClassiqValueError
17
+ from classiq.qmod.builtins.enums import Pauli, QSVMFeatureMapEntanglement
18
+ from classiq.qmod.utilities import qmod_val_to_expr_str
19
19
 
20
20
  INVALID_FEATURE_MAP_FUNC_NAME_MSG = "Invalid feature_map_function_name, it can be bloch_sphere_feature_map or pauli_feature_map"
21
21
 
@@ -24,43 +24,46 @@ _OUTPUT_VARIABLE_NAME = "qsvm_results"
24
24
 
25
25
  def _bloch_sphere_feature_map_function_params(
26
26
  bloch_feature_dimension: int,
27
- ) -> Tuple[Dict[str, Expression], str]:
28
- return {
29
- "feature_dimension": Expression(expr=f"{bloch_feature_dimension}")
30
- }, f"ceiling({bloch_feature_dimension}/2)"
27
+ ) -> tuple[list[Expression], str]:
28
+ return [
29
+ Expression(expr=f"{bloch_feature_dimension}")
30
+ ], f"ceiling({bloch_feature_dimension}/2)"
31
31
 
32
32
 
33
33
  def _pauli_feature_map_function_params(
34
- paulis: List[List[Pauli]],
34
+ paulis: list[list[Pauli]],
35
35
  entanglement: QSVMFeatureMapEntanglement,
36
36
  alpha: int,
37
37
  reps: int,
38
38
  feature_dimension: int,
39
- ) -> Tuple[Dict[str, Expression], str]:
39
+ ) -> tuple[list[Expression], str]:
40
40
  paulis_str = (
41
41
  "["
42
42
  + ",".join(
43
- ["[" + ",".join([str(p) for p in p_list]) + "]" for p_list in paulis]
43
+ [
44
+ "[" + ",".join([qmod_val_to_expr_str(p) for p in p_list]) + "]"
45
+ for p_list in paulis
46
+ ]
44
47
  )
45
48
  + "]"
46
49
  )
47
50
  pauli_feature_map_params = (
48
51
  f"paulis={paulis_str}, "
49
- f"entanglement={entanglement}, "
52
+ f"entanglement={qmod_val_to_expr_str(entanglement)}, "
50
53
  f"alpha={alpha}, "
51
54
  f"reps={reps}, "
52
55
  f"feature_dimension={feature_dimension}"
53
56
  )
54
- return {
55
- "feature_map": Expression(
57
+ return [
58
+ Expression(
56
59
  expr=f"struct_literal(QSVMFeatureMapPauli, {pauli_feature_map_params})"
57
60
  )
58
- }, f"{feature_dimension}"
61
+ ], f"{feature_dimension}"
59
62
 
60
63
 
61
64
  def get_qsvm_qmain_body(
62
65
  feature_map_function_name: str, **kwargs: Any
63
- ) -> List[QuantumFunctionCall]:
66
+ ) -> list[QuantumStatement]:
64
67
  if feature_map_function_name == "bloch_sphere_feature_map":
65
68
  params, size_expr = _bloch_sphere_feature_map_function_params(**kwargs)
66
69
  elif feature_map_function_name == "pauli_feature_map":
@@ -69,14 +72,13 @@ def get_qsvm_qmain_body(
69
72
  raise ClassiqValueError(INVALID_FEATURE_MAP_FUNC_NAME_MSG)
70
73
 
71
74
  return [
72
- QuantumFunctionCall(
73
- function="allocate",
74
- positional_args=[Expression(expr=size_expr), HandleBinding(name="qbv")],
75
+ Allocate(
76
+ size=Expression(expr=size_expr),
77
+ target=HandleBinding(name="qbv"),
75
78
  ),
76
79
  QuantumFunctionCall(
77
80
  function=feature_map_function_name,
78
- params=params,
79
- inouts={"qbv": HandleBinding(name="qbv")},
81
+ positional_args=[*params, HandleBinding(name="qbv")],
80
82
  ),
81
83
  ]
82
84
 
@@ -94,12 +96,12 @@ def construct_qsvm_model(
94
96
  functions=[
95
97
  NativeFunctionDefinition(
96
98
  name="main",
97
- port_declarations={
98
- "qbv": PortDeclaration(
99
+ positional_arg_declarations=[
100
+ PortDeclaration(
99
101
  name="qbv",
100
102
  direction=PortDeclarationDirection.Output,
101
- )
102
- },
103
+ ),
104
+ ],
103
105
  body=get_qsvm_qmain_body(
104
106
  feature_map_function_name=feature_map_function_name, **kwargs
105
107
  ),
@@ -114,7 +116,7 @@ def construct_qsvm_model(
114
116
  predict_data={predict_data}
115
117
  )
116
118
  save({{{_OUTPUT_VARIABLE_NAME!r}: {_OUTPUT_VARIABLE_NAME}}})
117
- """,
119
+ """.strip(),
118
120
  )
119
121
 
120
122
  return qsvm_qmod.get_model()
@@ -1,5 +1,3 @@
1
- from typing import List
2
-
3
1
  from ..executor import * # noqa: F403
4
2
  from ..executor import __all__ as _exec_all
5
3
  from ..interface.backend.backend_preferences import * # noqa: F403
@@ -9,7 +7,10 @@ from ..interface.executor.execution_preferences import __all__ as _ep_all
9
7
  from ..interface.executor.iqae_result import IQAEResult
10
8
  from ..interface.executor.result import ExecutionDetails
11
9
  from ..interface.executor.vqe_result import VQESolverResult
10
+ from .execution_session import ExecutionSession
11
+ from .iqcc import generate_iqcc_token, generate_iqcc_token_async
12
12
  from .jobs import ExecutionJob, get_execution_jobs, get_execution_jobs_async
13
+ from .qnn import execute_qnn
13
14
 
14
15
  __all__ = (
15
16
  _be_all
@@ -22,9 +23,13 @@ __all__ = (
22
23
  "ExecutionJob",
23
24
  "get_execution_jobs",
24
25
  "get_execution_jobs_async",
26
+ "ExecutionSession",
27
+ "execute_qnn",
28
+ "generate_iqcc_token",
29
+ "generate_iqcc_token_async",
25
30
  ]
26
31
  )
27
32
 
28
33
 
29
- def __dir__() -> List[str]:
34
+ def __dir__() -> list[str]:
30
35
  return __all__
@@ -0,0 +1,11 @@
1
+ from classiq.interface.hardware import HardwareInformation
2
+
3
+ from classiq._internals import async_utils
4
+ from classiq._internals.api_wrapper import ApiWrapper
5
+
6
+
7
+ def get_all_hardware_devices() -> list[HardwareInformation]:
8
+ """
9
+ Returns a list of all hardware devices known to Classiq.
10
+ """
11
+ return async_utils.run(ApiWrapper.call_get_all_hardware_devices())
@@ -0,0 +1,400 @@
1
+ import json
2
+ import random
3
+ from types import TracebackType
4
+ from typing import Callable, Optional, Union, cast
5
+
6
+ import numpy as np
7
+
8
+ from classiq.interface.chemistry.operator import PauliOperator, pauli_integers_to_str
9
+ from classiq.interface.exceptions import ClassiqError, ClassiqValueError
10
+ from classiq.interface.execution.primitives import EstimateInput, PrimitivesInput
11
+ from classiq.interface.executor.execution_preferences import ExecutionPreferences
12
+ from classiq.interface.executor.result import (
13
+ EstimationResult,
14
+ ExecutionDetails,
15
+ ParsedState,
16
+ )
17
+ from classiq.interface.generator.arith import number_utils
18
+ from classiq.interface.generator.functions.qmod_python_interface import QmodPyStruct
19
+ from classiq.interface.generator.quantum_program import QuantumProgram
20
+ from classiq.interface.model.quantum_type import QuantumBit, QuantumNumeric
21
+
22
+ from classiq._internals import async_utils
23
+ from classiq._internals.api_wrapper import ApiWrapper
24
+ from classiq._internals.client import client
25
+ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import (
26
+ _pauli_dict_to_pauli_terms,
27
+ )
28
+ from classiq.execution.jobs import ExecutionJob
29
+ from classiq.qmod.builtins import PauliTerm
30
+ from classiq.qmod.builtins.classical_execution_primitives import (
31
+ CARRAY_SEPARATOR,
32
+ ExecutionParams,
33
+ )
34
+ from classiq.synthesis import SerializedQuantumProgram
35
+
36
+ Hamiltonian = Union[list[QmodPyStruct], list[PauliTerm]]
37
+ Program = Union[SerializedQuantumProgram, QuantumProgram]
38
+ ParsedExecutionParams = dict[str, Union[float, int]]
39
+ ExecutionParameters = Optional[Union[ExecutionParams, list[ExecutionParams]]]
40
+ ParsedExecutionParameters = Optional[
41
+ Union[ParsedExecutionParams, list[ParsedExecutionParams]]
42
+ ]
43
+
44
+
45
+ def _deserialize_program(program: Program) -> QuantumProgram:
46
+ return (
47
+ program
48
+ if isinstance(program, QuantumProgram)
49
+ else QuantumProgram.model_validate(json.loads(program))
50
+ )
51
+
52
+
53
+ def hamiltonian_to_pauli_terms(hamiltonian: Hamiltonian) -> list[PauliTerm]:
54
+ if isinstance(hamiltonian[0], PauliTerm):
55
+ return cast(list[PauliTerm], hamiltonian)
56
+ else:
57
+ return _pauli_dict_to_pauli_terms(cast(list[QmodPyStruct], hamiltonian))
58
+
59
+
60
+ def _hamiltonian_to_pauli_operator(hamiltonian: Hamiltonian) -> PauliOperator:
61
+ pauli_list = [
62
+ (
63
+ pauli_integers_to_str(elem.pauli), # type: ignore[arg-type]
64
+ elem.coefficient,
65
+ )
66
+ for elem in hamiltonian_to_pauli_terms(hamiltonian)
67
+ ]
68
+ return PauliOperator(pauli_list=pauli_list)
69
+
70
+
71
+ def parse_params(params: ExecutionParams) -> ParsedExecutionParams:
72
+ result = {}
73
+ for key, values in params.items():
74
+ if isinstance(values, list):
75
+ for index, value in enumerate(values):
76
+ new_key = f"{key}{CARRAY_SEPARATOR}{index}"
77
+ result[new_key] = value
78
+ elif isinstance(values, (int, float)):
79
+ result[key] = values
80
+ else:
81
+ raise TypeError("Parameters were provided in un-supported format")
82
+ return result
83
+
84
+
85
+ class ExecutionSession:
86
+ """
87
+ A session for executing a quantum program.
88
+ `ExecutionSession` allows to execute the quantum program with different parameters and operations without the need to re-synthesize the model.
89
+ The session must be closed in order to ensure resources are properly cleaned up. It's recommended to use `ExecutionSession` as a context manager for this purpose. Alternatively, you can directly use the `close` method.
90
+
91
+ Attributes:
92
+ quantum_program (Union[SerializedQuantumProgram, QuantumProgram]): The quantum program to execute.
93
+ execution_preferences (Optional[ExecutionPreferences]): Execution preferences for the Quantum Program.
94
+ """
95
+
96
+ def __init__(
97
+ self,
98
+ quantum_program: Program,
99
+ execution_preferences: Optional[ExecutionPreferences] = None,
100
+ ):
101
+ self.program: QuantumProgram = _deserialize_program(quantum_program)
102
+ self.update_execution_preferences(execution_preferences)
103
+ # We never use classical_execution_code in ExecutionSession, and we don't want
104
+ # the conversion route to fail because cmain is expected in some cases
105
+ self.program.model.classical_execution_code = "dummy"
106
+
107
+ self._random_seed = self.program.model.execution_preferences.random_seed
108
+ self._rng = random.Random(self._random_seed) # noqa: S311
109
+
110
+ self._async_client = client().async_client()
111
+
112
+ self._session_id: str | None = None
113
+
114
+ def __enter__(self) -> "ExecutionSession":
115
+ return self
116
+
117
+ def __exit__(
118
+ self,
119
+ exc_type: Optional[type[BaseException]],
120
+ exc_val: Optional[BaseException],
121
+ exc_tb: Optional[TracebackType],
122
+ ) -> None:
123
+ self.close()
124
+
125
+ def close(self) -> None:
126
+ """
127
+ Close the session and clean up its resources.
128
+ """
129
+ async_utils.run(self._async_client.aclose())
130
+
131
+ def get_session_id(self) -> str:
132
+ if self._session_id is None:
133
+ self._session_id = async_utils.run(
134
+ ApiWrapper.call_create_execution_session(
135
+ self.program, self._async_client
136
+ )
137
+ )
138
+ return self._session_id
139
+
140
+ def _execute(self, primitives_input: PrimitivesInput) -> ExecutionJob:
141
+ primitives_input.random_seed = self._random_seed
142
+ self._random_seed = self._rng.randint(0, 2**32 - 1)
143
+ result = async_utils.run(
144
+ ApiWrapper.call_create_session_job(
145
+ self.get_session_id(), primitives_input, self._async_client
146
+ )
147
+ )
148
+ return ExecutionJob(details=result)
149
+
150
+ def update_execution_preferences(
151
+ self, execution_preferences: Optional[ExecutionPreferences]
152
+ ) -> None:
153
+ """
154
+ Update the execution preferences for the session.
155
+
156
+ Args:
157
+ execution_preferences: The execution preferences to update.
158
+
159
+ Returns:
160
+ None
161
+ """
162
+ if execution_preferences is not None:
163
+ self.program.model.execution_preferences = execution_preferences
164
+
165
+ def sample(self, parameters: Optional[ExecutionParams] = None) -> ExecutionDetails:
166
+ """
167
+ Samples the quantum program with the given parameters, if any.
168
+
169
+ Args:
170
+ parameters: The values to set for the parameters of the quantum program when sampling. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter.
171
+
172
+ Returns:
173
+ The result of the sampling.
174
+ """
175
+ job = self.submit_sample(parameters=parameters)
176
+ return job.get_sample_result(_http_client=self._async_client)
177
+
178
+ def submit_sample(
179
+ self, parameters: Optional[ExecutionParams] = None
180
+ ) -> ExecutionJob:
181
+ """
182
+ Initiates an execution job with the `sample` primitive.
183
+
184
+ This is a non-blocking version of `sample`: it gets the same parameters and initiates the same execution job, but instead
185
+ of waiting for the result, it returns the job object immediately.
186
+
187
+ Args:
188
+ parameters: The values to set for the parameters of the quantum program when sampling. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter.
189
+
190
+ Returns:
191
+ The execution job.
192
+ """
193
+ execution_primitives_input = PrimitivesInput(
194
+ sample=[parse_params(parameters)] if parameters is not None else [{}]
195
+ )
196
+ return self._execute(execution_primitives_input)
197
+
198
+ def batch_sample(self, parameters: list[ExecutionParams]) -> list[ExecutionDetails]:
199
+ """
200
+ Samples the quantum program multiple times with the given parameters for each iteration. The number of samples is determined by the length of the parameters list.
201
+
202
+ Args:
203
+ parameters: A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter.
204
+
205
+ Returns:
206
+ List[ExecutionDetails]: The results of all the sampling iterations.
207
+ """
208
+ job = self.submit_batch_sample(parameters=parameters)
209
+ return job.get_batch_sample_result(_http_client=self._async_client)
210
+
211
+ def submit_batch_sample(self, parameters: list[ExecutionParams]) -> ExecutionJob:
212
+ """
213
+ Initiates an execution job with the `batch_sample` primitive.
214
+
215
+ This is a non-blocking version of `batch_sample`: it gets the same parameters and initiates the same execution job, but instead
216
+ of waiting for the result, it returns the job object immediately.
217
+
218
+ Args:
219
+ parameters: A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter.
220
+
221
+ Returns:
222
+ The execution job.
223
+ """
224
+ execution_primitives_input = PrimitivesInput(
225
+ sample=[parse_params(params) for params in parameters]
226
+ )
227
+ return self._execute(execution_primitives_input)
228
+
229
+ def estimate(
230
+ self, hamiltonian: Hamiltonian, parameters: Optional[ExecutionParams] = None
231
+ ) -> EstimationResult:
232
+ """
233
+ Estimates the expectation value of the given Hamiltonian using the quantum program.
234
+
235
+ Args:
236
+ hamiltonian: The Hamiltonian to estimate the expectation value of.
237
+ parameters: The values to set for the parameters of the quantum program when estimating. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter.
238
+
239
+ Returns:
240
+ EstimationResult: The result of the estimation.
241
+ """
242
+ job = self.submit_estimate(hamiltonian=hamiltonian, parameters=parameters)
243
+ return job.get_estimate_result(_http_client=self._async_client)
244
+
245
+ def submit_estimate(
246
+ self, hamiltonian: Hamiltonian, parameters: Optional[ExecutionParams] = None
247
+ ) -> ExecutionJob:
248
+ """
249
+ Initiates an execution job with the `estimate` primitive.
250
+
251
+ This is a non-blocking version of `estimate`: it gets the same parameters and initiates the same execution job, but instead
252
+ of waiting for the result, it returns the job object immediately.
253
+
254
+ Args:
255
+ hamiltonian: The Hamiltonian to estimate the expectation value of.
256
+ parameters: The values to set for the parameters of the quantum program when estimating. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter.
257
+
258
+ Returns:
259
+ The execution job.
260
+ """
261
+ execution_primitives_input = PrimitivesInput(
262
+ estimate=EstimateInput(
263
+ hamiltonian=_hamiltonian_to_pauli_operator(hamiltonian),
264
+ parameters=(
265
+ [parse_params(parameters)] if parameters is not None else [{}]
266
+ ),
267
+ )
268
+ )
269
+ return self._execute(execution_primitives_input)
270
+
271
+ def batch_estimate(
272
+ self, hamiltonian: Hamiltonian, parameters: list[ExecutionParams]
273
+ ) -> list[EstimationResult]:
274
+ """
275
+ Estimates the expectation value of the given Hamiltonian multiple times using the quantum program, with the given parameters for each iteration. The number of estimations is determined by the length of the parameters list.
276
+
277
+ Args:
278
+ hamiltonian: The Hamiltonian to estimate the expectation value of.
279
+ parameters: A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter.
280
+
281
+ Returns:
282
+ List[EstimationResult]: The results of all the estimation iterations.
283
+ """
284
+ job = self.submit_batch_estimate(hamiltonian=hamiltonian, parameters=parameters)
285
+ return job.get_batch_estimate_result(_http_client=self._async_client)
286
+
287
+ def submit_batch_estimate(
288
+ self, hamiltonian: Hamiltonian, parameters: list[ExecutionParams]
289
+ ) -> ExecutionJob:
290
+ """
291
+ Initiates an execution job with the `batch_estimate` primitive.
292
+
293
+ This is a non-blocking version of `batch_estimate`: it gets the same parameters and initiates the same execution job, but instead
294
+ of waiting for the result, it returns the job object immediately.
295
+
296
+ Args:
297
+ hamiltonian: The Hamiltonian to estimate the expectation value of.
298
+ parameters: A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter.
299
+
300
+ Returns:
301
+ The execution job.
302
+ """
303
+ execution_primitives_input = PrimitivesInput(
304
+ estimate=EstimateInput(
305
+ hamiltonian=_hamiltonian_to_pauli_operator(hamiltonian),
306
+ parameters=[parse_params(params) for params in parameters],
307
+ )
308
+ )
309
+ return self._execute(execution_primitives_input)
310
+
311
+ def estimate_cost(
312
+ self,
313
+ cost_func: Callable[[ParsedState], float],
314
+ parameters: Optional[ExecutionParams] = None,
315
+ quantile: float = 1.0,
316
+ ) -> float:
317
+ """
318
+ Estimates circuit cost using a classical cost function.
319
+
320
+ Args:
321
+ cost_func: classical circuit sample cost function
322
+ parameters: execution parameters sent to 'sample'
323
+ quantile: drop cost values outside the specified quantile
324
+
325
+ Returns:
326
+ cost estimation
327
+
328
+ See Also:
329
+ sample
330
+ """
331
+ if quantile < 0 or quantile > 1:
332
+ raise ClassiqValueError("'quantile' must be between 0 and 1")
333
+ res = self.sample(parameters)
334
+
335
+ counts = np.array(res.parsed_counts)
336
+ costs = np.vectorize(lambda sample: cost_func(sample.state))(counts)
337
+ shots = np.vectorize(lambda sample: sample.shots)(counts)
338
+
339
+ if quantile == 1:
340
+ return float(np.average(costs, weights=shots))
341
+ costs = np.repeat(costs, shots)
342
+ sort_idx = costs.argsort()
343
+ sort_idx = sort_idx[: int(quantile * len(costs))]
344
+ costs = costs[sort_idx]
345
+ if costs.size == 0:
346
+ return np.nan
347
+ return float(np.average(costs))
348
+
349
+ def set_measured_state_filter(
350
+ self,
351
+ output_name: str,
352
+ condition: Callable,
353
+ ) -> None:
354
+ """
355
+ EXPERIMENTAL
356
+
357
+ When simulating on a statevector simulator, emulate the behavior of postprocessing
358
+ by discarding amplitudes for which their states are "undesirable".
359
+
360
+ Args:
361
+ output_name: The name of the register to filter
362
+ condition: Filter out values of the statevector for which this callable is False
363
+ """
364
+ if self._session_id is not None:
365
+ raise ClassiqError(
366
+ "set_measured_state_filter must be called before use of the first primitive (sample, estimate...)"
367
+ )
368
+
369
+ if output_name not in self.program.model.circuit_outputs:
370
+ raise ClassiqValueError(f"{output_name} is not an output of the model")
371
+ output_type = self.program.model.circuit_output_types[output_name].quantum_types
372
+
373
+ legal_bitstrings = []
374
+
375
+ if isinstance(output_type, QuantumBit):
376
+ if condition(0):
377
+ legal_bitstrings.append("0")
378
+ if condition(1):
379
+ legal_bitstrings.append("1")
380
+ elif isinstance(output_type, QuantumNumeric):
381
+ size = output_type.size_in_bits
382
+ for i in range(2**size):
383
+ number_string = f"{i:0{size}b}"
384
+ val = number_utils.binary_to_float_or_int(
385
+ number_string,
386
+ output_type.fraction_digits_value,
387
+ output_type.sign_value,
388
+ )
389
+ if condition(val):
390
+ legal_bitstrings.append(number_string)
391
+ if len(legal_bitstrings) > 1:
392
+ raise NotImplementedError(
393
+ "Filtering is only supported on a single value per model output"
394
+ )
395
+ else:
396
+ raise NotImplementedError(
397
+ "Filtering is only supported on QuantumBit and QuantumNumeric"
398
+ )
399
+
400
+ self.program.model.register_filter_bitstrings[output_name] = legal_bitstrings
@@ -0,0 +1,63 @@
1
+ import time
2
+ import webbrowser
3
+
4
+ from classiq.interface.exceptions import ClassiqError
5
+ from classiq.interface.execution.iqcc import IQCCInitAuthData, IQCCProbeAuthData
6
+
7
+ from classiq._internals.api_wrapper import ApiWrapper
8
+ from classiq._internals.async_utils import syncify_function
9
+
10
+
11
+ async def generate_iqcc_token_async(
12
+ auth_scope_id: str,
13
+ auth_method_id: str,
14
+ timeout: float = 120,
15
+ probe_interval: float = 1,
16
+ print_auth_url: bool = True,
17
+ ) -> str:
18
+ """Interactively generate a token for use in IQCC backends.
19
+
20
+ Args:
21
+ auth_scope_id: The ID of the IQCC Boundary authentication scope.
22
+ auth_method_id: The ID of the IQCC Boundary authentication method.
23
+ timeout: Number of seconds to wait for the interactive authentication to complete.
24
+ probe_interval: Number of seconds to wait between probes of the authentication.
25
+ print_auth_url: Whether to print the authentication URL, useful for headless machines with no browser.
26
+
27
+ Returns:
28
+ The authentication token string to use directly in `IQCCBackendPreferences`.
29
+
30
+ Raises:
31
+ ClassiqError: In case timeout has reached before a successful authentication.
32
+ """
33
+ initiate_response = await ApiWrapper().call_iqcc_init_auth(
34
+ IQCCInitAuthData(auth_scope_id=auth_scope_id, auth_method_id=auth_method_id)
35
+ )
36
+
37
+ if print_auth_url:
38
+ print("Please proceed with authentication on your web browser.") # noqa: T201
39
+ print("If no window has opened, use this link to authenticate:") # noqa: T201
40
+ print(initiate_response.auth_url) # noqa: T201
41
+
42
+ webbrowser.open_new_tab(initiate_response.auth_url)
43
+
44
+ start_time = time.monotonic()
45
+ while True:
46
+ time.sleep(probe_interval)
47
+ probe_response = await ApiWrapper().call_iqcc_probe_auth(
48
+ IQCCProbeAuthData(
49
+ auth_scope_id=auth_scope_id,
50
+ auth_method_id=auth_method_id,
51
+ token_id=initiate_response.token_id,
52
+ )
53
+ )
54
+ if probe_response is not None:
55
+ return probe_response.auth_token
56
+
57
+ if time.monotonic() - start_time > timeout:
58
+ raise ClassiqError(
59
+ f"Timeout has reached while probing IQCC authentication. Please try again and make sure to authenticate within {timeout} seconds, or increase the timeout."
60
+ )
61
+
62
+
63
+ generate_iqcc_token = syncify_function(generate_iqcc_token_async)