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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. classiq/__init__.py +23 -24
  2. classiq/_analyzer_extras/_ipywidgets_async_extension.py +1 -1
  3. classiq/_analyzer_extras/interactive_hardware.py +3 -3
  4. classiq/_internals/api_wrapper.py +37 -17
  5. classiq/_internals/async_utils.py +1 -74
  6. classiq/_internals/authentication/device.py +9 -4
  7. classiq/_internals/authentication/password_manager.py +25 -10
  8. classiq/_internals/authentication/token_manager.py +2 -2
  9. classiq/_internals/client.py +24 -6
  10. classiq/_internals/jobs.py +10 -7
  11. classiq/analyzer/analyzer.py +29 -29
  12. classiq/analyzer/analyzer_utilities.py +5 -5
  13. classiq/analyzer/rb.py +4 -5
  14. classiq/analyzer/show_interactive_hack.py +6 -6
  15. classiq/applications/__init__.py +1 -8
  16. classiq/applications/chemistry/__init__.py +6 -0
  17. classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +9 -16
  18. classiq/applications/combinatorial_helpers/allowed_constraints.py +20 -0
  19. classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
  20. classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
  21. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +150 -0
  22. classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
  23. classiq/applications/combinatorial_helpers/encoding_utils.py +122 -0
  24. classiq/applications/combinatorial_helpers/memory.py +77 -0
  25. classiq/applications/combinatorial_helpers/optimization_model.py +162 -0
  26. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
  27. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +75 -0
  28. classiq/applications/combinatorial_helpers/py.typed +0 -0
  29. classiq/applications/combinatorial_helpers/pyomo_utils.py +245 -0
  30. classiq/applications/combinatorial_helpers/solvers/__init__.py +0 -0
  31. classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
  32. classiq/applications/combinatorial_helpers/transformations/__init__.py +0 -0
  33. classiq/applications/combinatorial_helpers/transformations/encoding.py +187 -0
  34. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +142 -0
  35. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +122 -0
  36. classiq/applications/combinatorial_helpers/transformations/penalty.py +32 -0
  37. classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
  38. classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +75 -0
  39. classiq/applications/combinatorial_helpers/transformations/slack_variables.py +88 -0
  40. classiq/applications/combinatorial_optimization/__init__.py +13 -2
  41. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +134 -0
  42. classiq/applications/finance/__init__.py +3 -2
  43. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +27 -30
  44. classiq/applications/grover/__init__.py +11 -0
  45. classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +20 -91
  46. classiq/applications/libraries/__init__.py +0 -0
  47. classiq/applications/libraries/qmci_library.py +35 -0
  48. classiq/applications/qnn/circuit_utils.py +2 -2
  49. classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
  50. classiq/applications/qnn/types.py +2 -2
  51. classiq/applications/qsvm/__init__.py +5 -1
  52. classiq/applications/qsvm/qsvm.py +4 -7
  53. classiq/applications/qsvm/qsvm_data_generation.py +2 -5
  54. classiq/exceptions.py +43 -1
  55. classiq/execution/all_hardware_devices.py +13 -0
  56. classiq/executor.py +12 -10
  57. classiq/interface/_version.py +1 -1
  58. classiq/interface/analyzer/analysis_params.py +6 -3
  59. classiq/interface/analyzer/result.py +12 -8
  60. classiq/interface/applications/qsvm.py +17 -3
  61. classiq/interface/ast_node.py +23 -0
  62. classiq/interface/backend/backend_preferences.py +4 -2
  63. classiq/interface/backend/pydantic_backend.py +3 -1
  64. classiq/interface/backend/quantum_backend_providers.py +1 -0
  65. classiq/interface/chemistry/fermionic_operator.py +15 -13
  66. classiq/interface/chemistry/ground_state_problem.py +18 -3
  67. classiq/interface/chemistry/molecule.py +8 -6
  68. classiq/interface/chemistry/operator.py +20 -14
  69. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -1
  70. classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
  71. classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
  72. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -2
  73. classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
  74. classiq/interface/combinatorial_optimization/examples/mht.py +8 -3
  75. classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
  76. classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
  77. classiq/interface/combinatorial_optimization/examples/set_cover.py +2 -1
  78. classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
  79. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
  80. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +9 -3
  81. classiq/interface/executor/aws_execution_cost.py +4 -3
  82. classiq/interface/executor/estimation.py +2 -2
  83. classiq/interface/executor/execution_preferences.py +5 -34
  84. classiq/interface/executor/execution_request.py +15 -48
  85. classiq/interface/executor/optimizer_preferences.py +22 -13
  86. classiq/interface/executor/{quantum_program.py → quantum_code.py} +21 -15
  87. classiq/interface/executor/quantum_instruction_set.py +2 -1
  88. classiq/interface/executor/register_initialization.py +1 -3
  89. classiq/interface/executor/result.py +41 -10
  90. classiq/interface/executor/vqe_result.py +2 -2
  91. classiq/interface/finance/function_input.py +17 -4
  92. classiq/interface/finance/gaussian_model_input.py +3 -1
  93. classiq/interface/finance/log_normal_model_input.py +3 -1
  94. classiq/interface/finance/model_input.py +2 -0
  95. classiq/interface/generator/amplitude_loading.py +6 -3
  96. classiq/interface/generator/application_apis/__init__.py +1 -0
  97. classiq/interface/generator/application_apis/arithmetic_declarations.py +14 -0
  98. classiq/interface/generator/arith/argument_utils.py +14 -4
  99. classiq/interface/generator/arith/arithmetic.py +3 -1
  100. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +12 -13
  101. classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -1
  102. classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -2
  103. classiq/interface/generator/arith/arithmetic_expression_validator.py +16 -2
  104. classiq/interface/generator/arith/arithmetic_operations.py +5 -10
  105. classiq/interface/generator/arith/ast_node_rewrite.py +1 -1
  106. classiq/interface/generator/arith/binary_ops.py +202 -54
  107. classiq/interface/generator/arith/extremum_operations.py +5 -3
  108. classiq/interface/generator/arith/logical_ops.py +4 -2
  109. classiq/interface/generator/arith/machine_precision.py +3 -0
  110. classiq/interface/generator/arith/number_utils.py +34 -44
  111. classiq/interface/generator/arith/register_user_input.py +21 -1
  112. classiq/interface/generator/arith/unary_ops.py +16 -25
  113. classiq/interface/generator/builtin_api_builder.py +0 -5
  114. classiq/interface/generator/chemistry_function_params.py +4 -4
  115. classiq/interface/generator/commuting_pauli_exponentiation.py +3 -1
  116. classiq/interface/generator/compiler_keywords.py +4 -0
  117. classiq/interface/generator/complex_type.py +3 -10
  118. classiq/interface/generator/constant.py +2 -3
  119. classiq/interface/generator/control_state.py +5 -3
  120. classiq/interface/generator/credit_risk_example/linear_gci.py +10 -3
  121. classiq/interface/generator/credit_risk_example/weighted_adder.py +14 -4
  122. classiq/interface/generator/expressions/atomic_expression_functions.py +5 -3
  123. classiq/interface/generator/expressions/evaluated_expression.py +18 -4
  124. classiq/interface/generator/expressions/expression.py +3 -5
  125. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +33 -0
  126. classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
  127. classiq/interface/generator/finance.py +1 -1
  128. classiq/interface/generator/function_params.py +7 -6
  129. classiq/interface/generator/functions/__init__.py +2 -2
  130. classiq/interface/generator/functions/builtins/__init__.py +15 -0
  131. classiq/interface/generator/functions/builtins/core_library/__init__.py +14 -0
  132. classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
  133. classiq/interface/generator/functions/builtins/internal_operators.py +62 -0
  134. classiq/interface/generator/functions/{core_lib_declarations/quantum_functions/std_lib_functions.py → builtins/open_lib_functions.py} +612 -219
  135. classiq/interface/generator/functions/builtins/quantum_operators.py +37 -0
  136. classiq/interface/generator/functions/classical_type.py +2 -4
  137. classiq/interface/generator/functions/foreign_function_definition.py +12 -4
  138. classiq/interface/generator/functions/function_declaration.py +2 -2
  139. classiq/interface/generator/functions/function_implementation.py +8 -4
  140. classiq/interface/generator/functions/native_function_definition.py +4 -2
  141. classiq/interface/generator/functions/register.py +4 -2
  142. classiq/interface/generator/functions/register_mapping_data.py +14 -10
  143. classiq/interface/generator/generated_circuit_data.py +2 -2
  144. classiq/interface/generator/grover_operator.py +5 -3
  145. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +5 -1
  146. classiq/interface/generator/hardware/hardware_data.py +6 -4
  147. classiq/interface/generator/hardware_efficient_ansatz.py +25 -8
  148. classiq/interface/generator/hartree_fock.py +13 -3
  149. classiq/interface/generator/linear_pauli_rotations.py +3 -1
  150. classiq/interface/generator/mcu.py +5 -3
  151. classiq/interface/generator/mcx.py +7 -5
  152. classiq/interface/generator/model/classical_main_validator.py +1 -1
  153. classiq/interface/generator/model/constraints.py +2 -1
  154. classiq/interface/generator/model/model.py +12 -20
  155. classiq/interface/generator/model/preferences/preferences.py +4 -3
  156. classiq/interface/generator/oracles/custom_oracle.py +4 -2
  157. classiq/interface/generator/oracles/oracle_abc.py +2 -2
  158. classiq/interface/generator/qpe.py +6 -4
  159. classiq/interface/generator/qsvm.py +5 -8
  160. classiq/interface/generator/quantum_function_call.py +21 -16
  161. classiq/interface/generator/{generated_circuit.py → quantum_program.py} +10 -14
  162. classiq/interface/generator/range_types.py +3 -1
  163. classiq/interface/generator/slice_parsing_utils.py +8 -3
  164. classiq/interface/generator/standard_gates/controlled_standard_gates.py +4 -2
  165. classiq/interface/generator/state_preparation/metrics.py +2 -1
  166. classiq/interface/generator/state_preparation/state_preparation.py +7 -5
  167. classiq/interface/generator/state_propagator.py +16 -5
  168. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  169. classiq/interface/generator/types/struct_declaration.py +10 -7
  170. classiq/interface/generator/ucc.py +6 -4
  171. classiq/interface/generator/unitary_gate.py +7 -3
  172. classiq/interface/generator/validations/flow_graph.py +6 -4
  173. classiq/interface/generator/validations/validator_functions.py +6 -4
  174. classiq/interface/hardware.py +2 -2
  175. classiq/interface/helpers/custom_encoders.py +3 -0
  176. classiq/interface/helpers/pydantic_model_helpers.py +0 -6
  177. classiq/interface/helpers/validation_helpers.py +1 -1
  178. classiq/interface/helpers/versioned_model.py +4 -1
  179. classiq/interface/ide/show.py +2 -2
  180. classiq/interface/jobs.py +72 -3
  181. classiq/interface/model/bind_operation.py +18 -11
  182. classiq/interface/model/call_synthesis_data.py +68 -0
  183. classiq/interface/model/classical_if.py +13 -0
  184. classiq/interface/model/classical_parameter_declaration.py +2 -3
  185. classiq/interface/model/control.py +16 -0
  186. classiq/interface/model/handle_binding.py +3 -2
  187. classiq/interface/model/inplace_binary_operation.py +2 -2
  188. classiq/interface/model/invert.py +10 -0
  189. classiq/interface/model/model.py +29 -22
  190. classiq/interface/model/native_function_definition.py +3 -5
  191. classiq/interface/model/power.py +12 -0
  192. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +9 -4
  193. classiq/interface/model/quantum_expressions/control_state.py +2 -2
  194. classiq/interface/model/quantum_function_call.py +33 -142
  195. classiq/interface/model/quantum_function_declaration.py +8 -0
  196. classiq/interface/model/quantum_if_operation.py +4 -5
  197. classiq/interface/model/quantum_lambda_function.py +58 -0
  198. classiq/{quantum_register.py → interface/model/quantum_register.py} +17 -9
  199. classiq/interface/model/quantum_statement.py +3 -2
  200. classiq/interface/model/quantum_type.py +58 -59
  201. classiq/interface/model/quantum_variable_declaration.py +3 -3
  202. classiq/interface/model/repeat.py +13 -0
  203. classiq/interface/model/resolvers/function_call_resolver.py +26 -0
  204. classiq/interface/model/statement_block.py +49 -0
  205. classiq/interface/model/validations/handles_validator.py +16 -18
  206. classiq/interface/model/within_apply_operation.py +11 -0
  207. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
  208. classiq/interface/server/routes.py +5 -4
  209. classiq/qmod/__init__.py +13 -6
  210. classiq/qmod/builtins/classical_execution_primitives.py +27 -36
  211. classiq/qmod/builtins/classical_functions.py +22 -12
  212. classiq/qmod/builtins/functions.py +272 -328
  213. classiq/qmod/builtins/operations.py +171 -35
  214. classiq/qmod/builtins/structs.py +15 -15
  215. classiq/qmod/cfunc.py +42 -0
  216. classiq/qmod/classical_function.py +6 -14
  217. classiq/qmod/declaration_inferrer.py +12 -21
  218. classiq/qmod/expression_query.py +23 -0
  219. classiq/qmod/model_state_container.py +2 -0
  220. classiq/qmod/native/__init__.py +0 -0
  221. classiq/qmod/native/expression_to_qmod.py +189 -0
  222. classiq/qmod/native/pretty_printer.py +340 -0
  223. classiq/qmod/qfunc.py +27 -0
  224. classiq/qmod/qmod_constant.py +100 -0
  225. classiq/qmod/qmod_parameter.py +36 -13
  226. classiq/qmod/qmod_struct.py +3 -3
  227. classiq/qmod/qmod_variable.py +148 -31
  228. classiq/qmod/quantum_callable.py +1 -0
  229. classiq/qmod/quantum_expandable.py +18 -19
  230. classiq/qmod/quantum_function.py +41 -8
  231. classiq/qmod/symbolic.py +48 -5
  232. classiq/qmod/symbolic_expr.py +9 -0
  233. classiq/qmod/utilities.py +13 -0
  234. classiq/qmod/write_qmod.py +39 -0
  235. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/METADATA +2 -1
  236. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/RECORD +244 -225
  237. {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/WHEEL +1 -1
  238. classiq/applications/benchmarking/__init__.py +0 -9
  239. classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
  240. classiq/applications/numpy_utils.py +0 -37
  241. classiq/applications_model_constructors/__init__.py +0 -17
  242. classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
  243. classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
  244. classiq/builtin_functions/__init__.py +0 -43
  245. classiq/builtin_functions/amplitude_loading.py +0 -3
  246. classiq/builtin_functions/binary_ops.py +0 -1
  247. classiq/builtin_functions/exponentiation.py +0 -5
  248. classiq/builtin_functions/qpe.py +0 -4
  249. classiq/builtin_functions/qsvm.py +0 -7
  250. classiq/builtin_functions/range_types.py +0 -5
  251. classiq/builtin_functions/standard_gates.py +0 -1
  252. classiq/builtin_functions/state_preparation.py +0 -6
  253. classiq/builtin_functions/suzuki_trotter.py +0 -3
  254. classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
  255. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  256. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
  257. classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
  258. classiq/interface/generator/types/combinatorial_problem.py +0 -26
  259. classiq/interface/model/numeric_reinterpretation.py +0 -25
  260. classiq/interface/model/operator_synthesis_data.py +0 -48
  261. classiq/model/__init__.py +0 -14
  262. classiq/model/composite_function_generator.py +0 -33
  263. classiq/model/function_handler.py +0 -466
  264. classiq/model/function_handler.pyi +0 -152
  265. classiq/model/logic_flow.py +0 -149
  266. classiq/model/logic_flow_change_handler.py +0 -71
  267. classiq/model/model.py +0 -246
  268. classiq/quantum_functions/__init__.py +0 -17
  269. classiq/quantum_functions/annotation_parser.py +0 -207
  270. classiq/quantum_functions/decorators.py +0 -22
  271. classiq/quantum_functions/function_library.py +0 -181
  272. classiq/quantum_functions/function_parser.py +0 -74
  273. classiq/quantum_functions/quantum_function.py +0 -236
  274. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
  275. /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
  276. /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/pauli_helpers/__init__.py} +0 -0
  277. /classiq/{applications_model_constructors → applications}/libraries/ampltitude_estimation_library.py +0 -0
  278. /classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +0 -0
  279. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/atomic_quantum_functions.py +0 -0
  280. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/exponentiation_functions.py +0 -0
@@ -1,22 +0,0 @@
1
- from typing import Callable, Optional, Union, overload
2
-
3
- from classiq.quantum_functions.quantum_function import QuantumFunction
4
-
5
-
6
- @overload
7
- def quantum_function(func: None = None, name: Optional[str] = None) -> Callable: ...
8
-
9
-
10
- @overload
11
- def quantum_function(func: Callable, name: Optional[str] = None) -> QuantumFunction: ...
12
-
13
-
14
- def quantum_function(
15
- func: Optional[Callable] = None, name: Optional[str] = None
16
- ) -> Union[QuantumFunction, Callable]:
17
- if func is None:
18
- return lambda func: quantum_function(func, name)
19
- else:
20
- qf = QuantumFunction()
21
- qf.add_implementation(func, name)
22
- return qf
@@ -1,181 +0,0 @@
1
- """Function library module, implementing facilities for adding user defined functions to the Classiq platform."""
2
-
3
- from typing import Any, Dict, List, Tuple, Type, Union
4
-
5
- from more_itertools import locate
6
-
7
- from classiq.interface.generator.functions import (
8
- SynthesisForeignFunctionDefinition,
9
- SynthesisNativeFunctionDefinition,
10
- SynthesisQuantumFunctionDeclaration,
11
- )
12
- from classiq.interface.generator.model.model import (
13
- MAIN_FUNCTION_NAME,
14
- ConcreteFunctionDefinition,
15
- )
16
- from classiq.interface.generator.user_defined_function_params import CustomFunction
17
- from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
18
-
19
- from classiq.exceptions import ClassiqValueError
20
- from classiq.quantum_functions.quantum_function import (
21
- QuantumFunction,
22
- QuantumFunctionFactory,
23
- )
24
-
25
- QASM_INTRO = 'OPENQASM 2.0;\ninclude "qelib1.inc";\n'
26
- QASM3_INTRO = 'OPENQASM 3.0;\ninclude "stdgates.inc";\n'
27
-
28
- _INVALID_FUNCTION_LIBRARY_ARGUMENT_ERROR_MSG: str = (
29
- "Argument is not a valid FunctionLibrary object"
30
- )
31
-
32
-
33
- class FunctionLibrary:
34
- """Facility to manage functions."""
35
-
36
- def __init__(
37
- self,
38
- *functions: Union[
39
- SynthesisQuantumFunctionDeclaration,
40
- QuantumFunction,
41
- Type[QuantumFunctionFactory],
42
- ],
43
- ) -> None:
44
- """
45
- Args:
46
- name (:obj:`str`, optional): The name of the function library.
47
- *functions (:obj:`SynthesisQuantumFunctionDeclaration`, optional): A list of functions to initialize the object.
48
- """
49
- self._data: List[ConcreteFunctionDefinition] = list()
50
- self._params: Dict[str, CustomFunction] = dict()
51
- self._func_factories: Dict[str, Type[QuantumFunctionFactory]] = dict()
52
-
53
- for f in functions:
54
- self.add_function(f)
55
-
56
- if MAIN_FUNCTION_NAME not in self.function_dict:
57
- self.add_function(
58
- SynthesisNativeFunctionDefinition(name=MAIN_FUNCTION_NAME)
59
- )
60
-
61
- def get_function(self, function_name: str) -> CustomFunction:
62
- return self._params[function_name]
63
-
64
- def get_function_factory(
65
- self, function_factory_name: str
66
- ) -> Type[QuantumFunctionFactory]:
67
- return self._func_factories[function_factory_name]
68
-
69
- def __getitem__(self, key: Any) -> CustomFunction:
70
- if isinstance(key, str):
71
- return self.get_function(key)
72
- else:
73
- raise ClassiqValueError("Invalid key")
74
-
75
- def add_function(
76
- self,
77
- function_data: Union[
78
- SynthesisQuantumFunctionDeclaration,
79
- QuantumFunction,
80
- Type[QuantumFunctionFactory],
81
- ],
82
- override_existing_functions: bool = False,
83
- ) -> None:
84
- """Adds a function to the function library.
85
-
86
- Args:
87
- function_data (SynthesisQuantumFunctionDeclaration): The function data object.
88
- override_existing_functions (:obj:`bool`, optional): Defaults to False.
89
-
90
- Returns:
91
- None
92
- """
93
- if isinstance(function_data, type) and issubclass(
94
- function_data, QuantumFunctionFactory
95
- ):
96
- self._func_factories[function_data.__name__] = function_data
97
- return
98
- if isinstance(function_data, QuantumFunction):
99
- function_data = function_data.function_data
100
-
101
- if not isinstance(
102
- function_data,
103
- (SynthesisForeignFunctionDefinition, SynthesisNativeFunctionDefinition),
104
- ):
105
- raise ClassiqValueError(
106
- f"Concrete function definition object expected, got {function_data.__class__.__name__}"
107
- )
108
-
109
- function_name = function_data.name
110
- if not override_existing_functions and function_name in self.function_dict:
111
- raise ClassiqValueError("Cannot override existing functions.")
112
-
113
- if isinstance(function_data, SynthesisNativeFunctionDefinition):
114
- for call in filter(
115
- lambda i: isinstance(i.function_params, CustomFunction),
116
- function_data.body,
117
- ):
118
- if self._data and call.function not in self.function_dict:
119
- raise ClassiqValueError(
120
- "FunctionLibrary: The function is not found in included library."
121
- )
122
-
123
- self._data.append(function_data)
124
- self._params[function_name] = self._to_params(function_data)
125
-
126
- @property
127
- def function_names(self) -> Tuple[str, ...]:
128
- """Get a tuple of the names of the functions in the library.
129
-
130
- Returns:
131
- The names of the functions in the library.
132
- """
133
- return tuple(self.function_dict.keys())
134
-
135
- @property
136
- def function_factory_names(self) -> Tuple[str, ...]:
137
- return tuple(self._func_factories.keys())
138
-
139
- @property
140
- def functions(self) -> List[ConcreteFunctionDefinition]:
141
- return list(self._data)
142
-
143
- @property
144
- def function_dict(self) -> Dict[str, SynthesisQuantumFunctionDeclaration]:
145
- return nameables_to_dict(self._data)
146
-
147
- def remove_function_definition(self, name: str) -> None:
148
- idx = list(locate(self.functions, lambda func: func.name == name))
149
- assert len(idx) == 1
150
- self._data.pop(idx[0])
151
-
152
- @staticmethod
153
- def _to_params(data: SynthesisQuantumFunctionDeclaration) -> CustomFunction:
154
- params = CustomFunction(
155
- input_decls=data.inputs,
156
- output_decls=data.outputs,
157
- )
158
- return params
159
-
160
- def __add__(self, other: "FunctionLibrary") -> "FunctionLibrary":
161
- if not isinstance(other, FunctionLibrary):
162
- raise ClassiqValueError(_INVALID_FUNCTION_LIBRARY_ARGUMENT_ERROR_MSG)
163
- joint_library = FunctionLibrary()
164
- for library in (self, other):
165
- for func in library.functions:
166
- if (
167
- func.name == MAIN_FUNCTION_NAME
168
- or func.name in joint_library.function_names
169
- ):
170
- continue
171
- joint_library.add_function(func)
172
- return joint_library
173
-
174
- def __iadd__(self, other: "FunctionLibrary") -> "FunctionLibrary":
175
- if not isinstance(other, FunctionLibrary):
176
- raise ClassiqValueError(_INVALID_FUNCTION_LIBRARY_ARGUMENT_ERROR_MSG)
177
- for func in other.functions:
178
- if func.name == MAIN_FUNCTION_NAME or func.name in self.function_names:
179
- continue
180
- self.add_function(func)
181
- return self
@@ -1,74 +0,0 @@
1
- import sys
2
- from types import FunctionType, MethodType
3
- from typing import Any, Callable, Tuple, _GenericAlias # type: ignore[attr-defined]
4
-
5
- if sys.version_info >= (3, 9):
6
- from types import GenericAlias
7
- else:
8
- GenericAlias = _GenericAlias
9
-
10
-
11
- from classiq.exceptions import ClassiqQFuncError
12
-
13
-
14
- class FunctionParser:
15
- def __init__(self, func: FunctionType) -> None:
16
- self._func = func
17
-
18
- @staticmethod
19
- def _extract_function_output_by_execution(func: FunctionType) -> Any:
20
- # Todo: Parse the type (annotations) of the arguments, and remove only those inheriting from QReg
21
- if func.__code__.co_kwonlyargcount:
22
- raise ClassiqQFuncError("kw only args are not supported")
23
-
24
- arg_count = func.__code__.co_argcount - ("self" in func.__code__.co_varnames)
25
- nones = [None] * arg_count
26
- return func(*nones)
27
-
28
- def extract_function_output(self) -> Any:
29
- output = self._extract_function_output_by_execution(func=self._func)
30
-
31
- self._validate_function_output(output)
32
-
33
- return output
34
-
35
- @staticmethod
36
- def _validate_function_output(output: Any) -> None:
37
- # Todo: validate QASM
38
-
39
- if type(output) is not str:
40
- raise ClassiqQFuncError(
41
- "Invalid output. Please return a string of OpenQASM2.0."
42
- )
43
-
44
-
45
- def _convert_class_to_function(cls: type) -> Tuple[FunctionType, str]:
46
- # Create instance
47
- try:
48
- inst = cls()
49
- except TypeError as exc:
50
- raise ClassiqQFuncError("Unable to initialize class") from exc
51
-
52
- return inst.__call__, inst.__class__.__name__
53
-
54
-
55
- def convert_callable_to_function(func: Callable) -> Tuple[FunctionType, str]:
56
- # There's a story to be told here:
57
- # Functions vs Methods.
58
- # It's a centuries old fight, which won't end soon..
59
- # Functions, being functions, always have a way of telling us about their functionality
60
- # This is done using `func.__code__`
61
- # Methods, being the heigher form of functions, are too proud to have a `__code__` attribute.
62
- # Thus, `"__code__" in method` is false
63
- # However, `method.__code__` exists
64
- # Since it is inherited from the class that initialized the instance who owns the method
65
- # Thus, we reach the important conclusion:
66
- # Methods are shy functions. They are functions, but they don't like telling us that they're functions.
67
- if not callable(func):
68
- raise ClassiqQFuncError("Invalid callable given.")
69
-
70
- if isinstance(func, (FunctionType, MethodType)):
71
- return func, func.__name__ # type: ignore[return-value]
72
-
73
- # Assuming `func` is an instance of some class
74
- return _convert_class_to_function(func) # type: ignore[arg-type]
@@ -1,236 +0,0 @@
1
- import sys
2
- from abc import ABC, abstractmethod
3
- from types import FunctionType
4
- from typing import Callable, Dict, List, Optional, Sequence, Tuple
5
-
6
- from classiq.interface.generator.functions import (
7
- FunctionImplementation,
8
- Register,
9
- RegisterMappingData,
10
- SynthesisForeignFunctionDefinition,
11
- )
12
- from classiq.interface.generator.register_role import RegisterRole as Role
13
-
14
- from classiq.exceptions import ClassiqError
15
-
16
- # This line is ignored because the entire annotation_parser module is ignored by mypy
17
- from classiq.quantum_functions.annotation_parser import ( # type: ignore[attr-defined]
18
- AnnotationParser,
19
- get_annotation_role,
20
- )
21
- from classiq.quantum_functions.function_parser import (
22
- FunctionParser,
23
- convert_callable_to_function,
24
- )
25
-
26
- # isort: split
27
- from typing import _GenericAlias # type: ignore[attr-defined]
28
-
29
- from classiq.quantum_register import QRegGenericAlias
30
-
31
- if sys.version_info >= (3, 9):
32
- from types import GenericAlias
33
- else:
34
- GenericAlias = _GenericAlias
35
-
36
-
37
- class QuantumFunction:
38
- def __init__(self) -> None:
39
- self._function_data: Optional[SynthesisForeignFunctionDefinition] = None
40
-
41
- @staticmethod
42
- def _generate_single_register(
43
- first_qubit: int, name: str, obj: GenericAlias
44
- ) -> Register:
45
- qreg_size = obj.size
46
-
47
- qubits = tuple(range(first_qubit, first_qubit + qreg_size))
48
-
49
- return Register(
50
- name=name,
51
- qubits=qubits,
52
- )
53
-
54
- @classmethod
55
- def _generate_registers(
56
- cls,
57
- input_names: Sequence[str],
58
- input_values: Sequence[QRegGenericAlias],
59
- output_values: Sequence[QRegGenericAlias],
60
- ) -> Dict[Role, Tuple[Register, ...]]:
61
- registers: Dict[Role, List[Register]] = {k: list() for k in Role}
62
-
63
- qubit_counter = 0
64
- for input_name, input_annotation in zip(input_names, input_values):
65
- role = get_annotation_role(
66
- annotation=input_annotation, default_role=Role.INPUT
67
- )
68
-
69
- registers[role].append(
70
- cls._generate_single_register(
71
- first_qubit=qubit_counter,
72
- name=input_name,
73
- obj=input_annotation,
74
- )
75
- )
76
-
77
- if input_annotation.size is None:
78
- raise ClassiqError("Missing size in input annotation")
79
-
80
- qubit_counter += input_annotation.size
81
-
82
- qubit_counter = 0
83
- for input_name, output_annotation in zip(input_names, output_values):
84
- role = get_annotation_role(
85
- annotation=output_annotation, default_role=Role.OUTPUT
86
- )
87
-
88
- if output_annotation.size is None:
89
- raise ClassiqError("Missing size in input annotation")
90
-
91
- if role == Role.AUXILIARY:
92
- qubit_counter += output_annotation.size
93
- continue
94
-
95
- registers[role].append(
96
- cls._generate_single_register(
97
- first_qubit=qubit_counter,
98
- name=input_name,
99
- obj=output_annotation,
100
- )
101
- )
102
- qubit_counter += output_annotation.size
103
-
104
- return {k: tuple(v) for k, v in registers.items()}
105
-
106
- @classmethod
107
- def _create_implementation_from_function(
108
- cls,
109
- func: FunctionType,
110
- func_name: str,
111
- auxiliary_registers: Tuple[Register, ...],
112
- ) -> FunctionImplementation:
113
- # Return value
114
- fp = FunctionParser(func)
115
- serialized_circuit = fp.extract_function_output()
116
-
117
- implementation = FunctionImplementation(
118
- name=func_name,
119
- serialized_circuit=serialized_circuit,
120
- auxiliary_registers=auxiliary_registers,
121
- )
122
- return implementation
123
-
124
- def add_implementation(
125
- self, func: Callable, name: Optional[str] = None
126
- ) -> "QuantumFunction":
127
- func, func_name = convert_callable_to_function(func=func)
128
- func_name = name or func_name
129
-
130
- # Annotations
131
- ap = AnnotationParser(func)
132
- ap.parse()
133
-
134
- registers: Dict[Role, Tuple[Register, ...]] = self._generate_registers(
135
- input_names=ap.input_names,
136
- input_values=ap.input_values,
137
- output_values=ap.output_values,
138
- )
139
-
140
- implementation = self._create_implementation_from_function(
141
- func=func,
142
- func_name=func_name,
143
- auxiliary_registers=registers[Role.AUXILIARY],
144
- )
145
-
146
- if self._function_data is None:
147
- self._function_data = SynthesisForeignFunctionDefinition(
148
- name=func_name,
149
- implementations=(implementation,),
150
- register_mapping=RegisterMappingData.from_registers_dict(
151
- regs_dict=registers
152
- ),
153
- )
154
- else:
155
- self._function_data.register_mapping.validate_equal_mappings(
156
- RegisterMappingData.from_registers_dict(regs_dict=registers)
157
- )
158
- current_implementations = self._function_data.implementations or tuple()
159
- new_implementations = current_implementations + (implementation,)
160
- implementation.validate_ranges_of_all_registers(
161
- self._function_data.register_mapping
162
- )
163
- self._function_data = SynthesisForeignFunctionDefinition(
164
- name=self._function_data.name,
165
- register_mapping=self._function_data.register_mapping,
166
- implementations=new_implementations,
167
- )
168
-
169
- return self
170
-
171
- @property
172
- def function_data(self) -> SynthesisForeignFunctionDefinition:
173
- if self._function_data is None:
174
- raise ClassiqError("Access to uninitialized function data")
175
-
176
- return self._function_data
177
-
178
- @function_data.setter
179
- def function_data(
180
- self, new_function_data: SynthesisForeignFunctionDefinition
181
- ) -> None:
182
- self._function_data = new_function_data
183
-
184
-
185
- class QuantumFunctionFactoryBadUsageError(Exception):
186
- def __init__(self, msg: str) -> None:
187
- self.message = f"{msg} Please call QuantumFunctionFactory.__init__ after initializing all user params."
188
- super().__init__(self.message)
189
-
190
-
191
- class QuantumFunctionFactory(ABC):
192
- """
193
- Provides the capability of creating parametrized user-defined functions.
194
- """
195
-
196
- def __init__(self, add_method: Callable, apply_method: Callable) -> None:
197
- self._apply_method = apply_method
198
- try:
199
- definition = self.definition
200
- except AttributeError as e:
201
- raise QuantumFunctionFactoryBadUsageError(
202
- f"{self.__class__.__name__} instance definition parsing failed."
203
- ) from e
204
- definition.function_data = definition.function_data.renamed(str(self))
205
- add_method(definition)
206
-
207
- def __str__(self) -> str:
208
- str_list = [self.__class__.__name__.lower()]
209
- str_list.extend(
210
- f"{k}_{abs(hash(str(v)))}"
211
- for k, v in self.__dict__.items()
212
- if k != "_apply_method"
213
- )
214
- return "_".join(str_list)
215
-
216
- def __call__(self, *args, **kwargs):
217
- try:
218
- return self._apply_method(str(self), *args, **kwargs)
219
- except AttributeError as e:
220
- raise QuantumFunctionFactoryBadUsageError(
221
- f"Could not call {self.__class__.__name__}."
222
- ) from e
223
-
224
- @property
225
- @abstractmethod
226
- def definition(self) -> QuantumFunction:
227
- """
228
- Abstract method for providing the definition of the user function.
229
- The QuantumFunction object may be generated either directly, or using existing
230
- helper tools such as the @qfunc decorator.
231
- Instance attributes of the QuantumFunctionFactory may be used as parameters for the
232
- definition.
233
-
234
- Returns:
235
- The user-defined QuantumFunction object.
236
- """