classiq 0.37.0__py3-none-any.whl → 0.38.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 (228) hide show
  1. classiq/__init__.py +2 -2
  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 +24 -16
  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 +13 -5
  10. classiq/_internals/jobs.py +10 -7
  11. classiq/analyzer/analyzer.py +26 -28
  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/benchmarking/mirror_benchmarking.py +9 -6
  16. classiq/applications/combinatorial_optimization/__init__.py +5 -0
  17. classiq/applications/qnn/circuit_utils.py +2 -2
  18. classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
  19. classiq/applications/qnn/types.py +2 -2
  20. classiq/applications/qsvm/qsvm.py +4 -7
  21. classiq/applications/qsvm/qsvm_data_generation.py +2 -5
  22. classiq/applications_model_constructors/__init__.py +9 -1
  23. classiq/applications_model_constructors/chemistry_model_constructor.py +9 -16
  24. classiq/applications_model_constructors/combinatorial_helpers/__init__.py +0 -0
  25. classiq/applications_model_constructors/combinatorial_helpers/allowed_constraints.py +20 -0
  26. classiq/applications_model_constructors/combinatorial_helpers/arithmetic/__init__.py +0 -0
  27. classiq/applications_model_constructors/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
  28. classiq/applications_model_constructors/combinatorial_helpers/arithmetic/isolation.py +42 -0
  29. classiq/applications_model_constructors/combinatorial_helpers/combinatorial_problem_utils.py +130 -0
  30. classiq/applications_model_constructors/combinatorial_helpers/encoding_mapping.py +107 -0
  31. classiq/applications_model_constructors/combinatorial_helpers/encoding_utils.py +122 -0
  32. classiq/applications_model_constructors/combinatorial_helpers/memory.py +79 -0
  33. classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +34 -0
  34. classiq/applications_model_constructors/combinatorial_helpers/optimization_model.py +166 -0
  35. classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
  36. classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
  37. classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +65 -0
  38. classiq/applications_model_constructors/combinatorial_helpers/py.typed +0 -0
  39. classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +243 -0
  40. classiq/applications_model_constructors/combinatorial_helpers/sympy_utils.py +22 -0
  41. classiq/applications_model_constructors/combinatorial_helpers/transformations/__init__.py +0 -0
  42. classiq/applications_model_constructors/combinatorial_helpers/transformations/encoding.py +194 -0
  43. classiq/applications_model_constructors/combinatorial_helpers/transformations/fixed_variables.py +144 -0
  44. classiq/applications_model_constructors/combinatorial_helpers/transformations/ising_converter.py +124 -0
  45. classiq/applications_model_constructors/combinatorial_helpers/transformations/penalty.py +32 -0
  46. classiq/applications_model_constructors/combinatorial_helpers/transformations/penalty_support.py +41 -0
  47. classiq/applications_model_constructors/combinatorial_helpers/transformations/sign_seperation.py +75 -0
  48. classiq/applications_model_constructors/combinatorial_helpers/transformations/slack_variables.py +90 -0
  49. classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +48 -91
  50. classiq/applications_model_constructors/finance_model_constructor.py +4 -17
  51. classiq/applications_model_constructors/grover_model_constructor.py +20 -91
  52. classiq/applications_model_constructors/libraries/qmci_library.py +17 -19
  53. classiq/builtin_functions/standard_gates.py +1 -1
  54. classiq/exceptions.py +43 -1
  55. classiq/executor.py +10 -9
  56. classiq/interface/_version.py +1 -1
  57. classiq/interface/analyzer/analysis_params.py +6 -3
  58. classiq/interface/analyzer/result.py +12 -4
  59. classiq/interface/applications/qsvm.py +13 -1
  60. classiq/interface/backend/backend_preferences.py +4 -2
  61. classiq/interface/backend/pydantic_backend.py +3 -1
  62. classiq/interface/backend/quantum_backend_providers.py +1 -0
  63. classiq/interface/chemistry/fermionic_operator.py +15 -13
  64. classiq/interface/chemistry/ground_state_problem.py +18 -3
  65. classiq/interface/chemistry/molecule.py +8 -6
  66. classiq/interface/chemistry/operator.py +20 -14
  67. classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -1
  68. classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
  69. classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
  70. classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -2
  71. classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
  72. classiq/interface/combinatorial_optimization/examples/mht.py +3 -3
  73. classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
  74. classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
  75. classiq/interface/combinatorial_optimization/examples/set_cover.py +2 -1
  76. classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
  77. classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
  78. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +9 -3
  79. classiq/interface/executor/aws_execution_cost.py +4 -3
  80. classiq/interface/executor/estimation.py +2 -2
  81. classiq/interface/executor/execution_preferences.py +5 -34
  82. classiq/interface/executor/execution_request.py +19 -17
  83. classiq/interface/executor/optimizer_preferences.py +22 -13
  84. classiq/interface/executor/{quantum_program.py → quantum_code.py} +21 -15
  85. classiq/interface/executor/quantum_instruction_set.py +2 -1
  86. classiq/interface/executor/register_initialization.py +1 -3
  87. classiq/interface/executor/result.py +41 -10
  88. classiq/interface/executor/vqe_result.py +1 -1
  89. classiq/interface/finance/function_input.py +17 -4
  90. classiq/interface/finance/gaussian_model_input.py +3 -1
  91. classiq/interface/finance/log_normal_model_input.py +3 -1
  92. classiq/interface/finance/model_input.py +2 -0
  93. classiq/interface/generator/amplitude_loading.py +6 -3
  94. classiq/interface/generator/application_apis/__init__.py +1 -0
  95. classiq/interface/generator/application_apis/arithmetic_declarations.py +14 -0
  96. classiq/interface/generator/arith/argument_utils.py +14 -4
  97. classiq/interface/generator/arith/arithmetic.py +3 -1
  98. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +12 -13
  99. classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -1
  100. classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -2
  101. classiq/interface/generator/arith/arithmetic_expression_validator.py +16 -2
  102. classiq/interface/generator/arith/arithmetic_operations.py +5 -10
  103. classiq/interface/generator/arith/ast_node_rewrite.py +1 -1
  104. classiq/interface/generator/arith/binary_ops.py +202 -54
  105. classiq/interface/generator/arith/extremum_operations.py +5 -3
  106. classiq/interface/generator/arith/logical_ops.py +4 -2
  107. classiq/interface/generator/arith/machine_precision.py +3 -0
  108. classiq/interface/generator/arith/number_utils.py +34 -44
  109. classiq/interface/generator/arith/register_user_input.py +21 -1
  110. classiq/interface/generator/arith/unary_ops.py +16 -25
  111. classiq/interface/generator/chemistry_function_params.py +4 -4
  112. classiq/interface/generator/commuting_pauli_exponentiation.py +3 -1
  113. classiq/interface/generator/compiler_keywords.py +4 -0
  114. classiq/interface/generator/complex_type.py +3 -10
  115. classiq/interface/generator/control_state.py +5 -3
  116. classiq/interface/generator/credit_risk_example/linear_gci.py +10 -3
  117. classiq/interface/generator/credit_risk_example/weighted_adder.py +14 -4
  118. classiq/interface/generator/expressions/atomic_expression_functions.py +5 -3
  119. classiq/interface/generator/expressions/evaluated_expression.py +18 -4
  120. classiq/interface/generator/expressions/expression.py +1 -1
  121. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +33 -0
  122. classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
  123. classiq/interface/generator/finance.py +1 -1
  124. classiq/interface/generator/function_params.py +7 -6
  125. classiq/interface/generator/functions/__init__.py +1 -1
  126. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +505 -138
  127. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +25 -99
  128. classiq/interface/generator/functions/foreign_function_definition.py +12 -4
  129. classiq/interface/generator/functions/function_implementation.py +8 -4
  130. classiq/interface/generator/functions/native_function_definition.py +4 -2
  131. classiq/interface/generator/functions/register.py +4 -2
  132. classiq/interface/generator/functions/register_mapping_data.py +14 -10
  133. classiq/interface/generator/generated_circuit_data.py +2 -2
  134. classiq/interface/generator/grover_operator.py +5 -3
  135. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +5 -1
  136. classiq/interface/generator/hardware/hardware_data.py +6 -4
  137. classiq/interface/generator/hardware_efficient_ansatz.py +25 -8
  138. classiq/interface/generator/hartree_fock.py +3 -1
  139. classiq/interface/generator/linear_pauli_rotations.py +3 -1
  140. classiq/interface/generator/mcu.py +5 -3
  141. classiq/interface/generator/mcx.py +7 -5
  142. classiq/interface/generator/model/constraints.py +2 -1
  143. classiq/interface/generator/model/model.py +11 -19
  144. classiq/interface/generator/model/preferences/preferences.py +4 -3
  145. classiq/interface/generator/oracles/custom_oracle.py +4 -2
  146. classiq/interface/generator/oracles/oracle_abc.py +2 -2
  147. classiq/interface/generator/qpe.py +6 -4
  148. classiq/interface/generator/qsvm.py +5 -8
  149. classiq/interface/generator/quantum_function_call.py +21 -16
  150. classiq/interface/generator/{generated_circuit.py → quantum_program.py} +10 -14
  151. classiq/interface/generator/range_types.py +3 -1
  152. classiq/interface/generator/slice_parsing_utils.py +8 -3
  153. classiq/interface/generator/standard_gates/controlled_standard_gates.py +4 -2
  154. classiq/interface/generator/state_preparation/metrics.py +2 -1
  155. classiq/interface/generator/state_preparation/state_preparation.py +7 -5
  156. classiq/interface/generator/state_propagator.py +16 -5
  157. classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
  158. classiq/interface/generator/types/struct_declaration.py +8 -3
  159. classiq/interface/generator/ucc.py +6 -4
  160. classiq/interface/generator/unitary_gate.py +7 -3
  161. classiq/interface/generator/validations/flow_graph.py +6 -4
  162. classiq/interface/generator/validations/validator_functions.py +6 -4
  163. classiq/interface/hardware.py +2 -2
  164. classiq/interface/helpers/custom_encoders.py +3 -0
  165. classiq/interface/helpers/pydantic_model_helpers.py +0 -6
  166. classiq/interface/helpers/validation_helpers.py +1 -1
  167. classiq/interface/helpers/versioned_model.py +4 -1
  168. classiq/interface/ide/show.py +2 -2
  169. classiq/interface/jobs.py +72 -3
  170. classiq/interface/model/bind_operation.py +18 -11
  171. classiq/interface/model/call_synthesis_data.py +68 -0
  172. classiq/interface/model/inplace_binary_operation.py +2 -2
  173. classiq/interface/model/model.py +27 -21
  174. classiq/interface/model/native_function_definition.py +3 -5
  175. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +9 -4
  176. classiq/interface/model/quantum_expressions/control_state.py +2 -2
  177. classiq/interface/model/quantum_function_call.py +25 -139
  178. classiq/interface/model/quantum_function_declaration.py +8 -0
  179. classiq/interface/model/quantum_if_operation.py +2 -3
  180. classiq/interface/model/quantum_lambda_function.py +64 -0
  181. classiq/interface/model/quantum_type.py +57 -56
  182. classiq/interface/model/quantum_variable_declaration.py +1 -1
  183. classiq/interface/model/statement_block.py +32 -0
  184. classiq/interface/model/validations/handles_validator.py +14 -12
  185. classiq/interface/model/within_apply_operation.py +11 -0
  186. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
  187. classiq/interface/server/routes.py +5 -0
  188. classiq/model/function_handler.py +5 -9
  189. classiq/model/model.py +2 -19
  190. classiq/qmod/__init__.py +13 -6
  191. classiq/qmod/builtins/classical_execution_primitives.py +27 -36
  192. classiq/qmod/builtins/classical_functions.py +24 -14
  193. classiq/qmod/builtins/functions.py +162 -145
  194. classiq/qmod/builtins/operations.py +24 -35
  195. classiq/qmod/builtins/structs.py +15 -15
  196. classiq/qmod/cfunc.py +42 -0
  197. classiq/qmod/classical_function.py +6 -14
  198. classiq/qmod/declaration_inferrer.py +12 -21
  199. classiq/qmod/expression_query.py +23 -0
  200. classiq/qmod/model_state_container.py +2 -0
  201. classiq/qmod/native/__init__.py +0 -0
  202. classiq/qmod/native/expression_to_qmod.py +189 -0
  203. classiq/qmod/native/pretty_printer.py +311 -0
  204. classiq/qmod/qfunc.py +27 -0
  205. classiq/qmod/qmod_constant.py +76 -0
  206. classiq/qmod/qmod_parameter.py +34 -12
  207. classiq/qmod/qmod_struct.py +3 -3
  208. classiq/qmod/qmod_variable.py +102 -18
  209. classiq/qmod/quantum_expandable.py +16 -16
  210. classiq/qmod/quantum_function.py +37 -8
  211. classiq/qmod/symbolic.py +47 -4
  212. classiq/qmod/symbolic_expr.py +9 -0
  213. classiq/qmod/utilities.py +13 -0
  214. classiq/qmod/write_qmod.py +39 -0
  215. classiq/quantum_functions/__init__.py +2 -2
  216. classiq/quantum_functions/annotation_parser.py +9 -11
  217. classiq/quantum_functions/function_parser.py +1 -1
  218. classiq/quantum_functions/quantum_function.py +3 -3
  219. classiq/quantum_register.py +17 -9
  220. {classiq-0.37.0.dist-info → classiq-0.38.0.dist-info}/METADATA +2 -1
  221. {classiq-0.37.0.dist-info → classiq-0.38.0.dist-info}/RECORD +222 -186
  222. {classiq-0.37.0.dist-info → classiq-0.38.0.dist-info}/WHEEL +1 -1
  223. classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
  224. classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
  225. classiq/interface/generator/types/combinatorial_problem.py +0 -26
  226. classiq/interface/model/numeric_reinterpretation.py +0 -25
  227. classiq/interface/model/operator_synthesis_data.py +0 -48
  228. classiq/model/function_handler.pyi +0 -152
@@ -4,7 +4,7 @@ from classiq.exceptions import ClassiqValueError
4
4
  def min_unsigned_bit_length(number: int) -> int:
5
5
  if number < 0:
6
6
  raise ClassiqValueError(
7
- f"Quantum register is not signed but control value " # noqa: B907
7
+ f"Quantum register is not signed but control value "
8
8
  f"'{number}' is negative"
9
9
  )
10
10
  return 1 if number == 0 else number.bit_length()
@@ -28,7 +28,7 @@ def to_twos_complement(value: int, bits: int, is_signed: bool) -> str:
28
28
  required_bits = min_bit_length(value, is_signed)
29
29
  if bits < required_bits:
30
30
  raise ClassiqValueError(
31
- f"Cannot express '{value}' using {bits} bits: " # noqa: B907
31
+ f"Cannot express '{value}' using {bits} bits: "
32
32
  f"at least {required_bits} bits are required"
33
33
  )
34
34
  if value >= 0:
@@ -1,49 +1,35 @@
1
1
  import itertools
2
2
  import re
3
- from typing import Any, Dict, List, Mapping, Optional, Sequence, Set, Union
3
+ from typing import Any, Dict, List, Mapping, Optional, Set, Union
4
4
 
5
5
  import pydantic
6
6
  from pydantic import BaseModel
7
7
 
8
8
  from classiq.interface.generator.expressions.expression import Expression
9
- from classiq.interface.generator.function_params import NAME_REGEX
10
- from classiq.interface.generator.functions import FunctionDeclaration
9
+ from classiq.interface.generator.functions.function_declaration import (
10
+ FunctionDeclaration,
11
+ )
11
12
  from classiq.interface.generator.functions.port_declaration import (
12
13
  PortDeclarationDirection,
13
14
  )
14
- from classiq.interface.generator.quantum_function_call import (
15
- BAD_CALL_NAME_ERROR_MSG,
16
- SUFFIX_MARKER,
17
- randomize_suffix,
18
- )
19
- from classiq.interface.helpers.custom_pydantic_types import PydanticNonEmptyString
20
- from classiq.interface.model.bind_operation import BindOperation
15
+ from classiq.interface.model.call_synthesis_data import CallSynthesisData
21
16
  from classiq.interface.model.handle_binding import (
22
17
  HandleBinding,
23
18
  SlicedHandleBinding,
24
19
  SubscriptHandleBinding,
25
20
  )
26
- from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
27
- from classiq.interface.model.numeric_reinterpretation import (
28
- NumericReinterpretationOperation,
29
- )
30
- from classiq.interface.model.operator_synthesis_data import OperatorSynthesisData
31
- from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
32
- AmplitudeLoadingOperation,
33
- )
34
- from classiq.interface.model.quantum_expressions.arithmetic_operation import (
35
- ArithmeticOperation,
36
- )
37
21
  from classiq.interface.model.quantum_function_declaration import (
38
22
  QuantumFunctionDeclaration,
39
23
  QuantumOperandDeclaration,
40
24
  )
41
- from classiq.interface.model.quantum_if_operation import QuantumIfOperation
25
+ from classiq.interface.model.quantum_lambda_function import (
26
+ LambdaListComprehension,
27
+ QuantumCallable,
28
+ QuantumLambdaFunction,
29
+ QuantumOperand,
30
+ )
42
31
  from classiq.interface.model.quantum_statement import QuantumOperation
43
32
  from classiq.interface.model.validation_handle import get_unique_handle_names
44
- from classiq.interface.model.variable_declaration_statement import (
45
- VariableDeclarationStatement,
46
- )
47
33
 
48
34
  from classiq.exceptions import ClassiqError, ClassiqValueError
49
35
 
@@ -108,7 +94,13 @@ def _validate_no_mixing_sliced_and_whole_handles(
108
94
  )
109
95
 
110
96
 
111
- ArgValue = Union[Expression, "QuantumOperand", SlicedHandleBinding, HandleBinding]
97
+ ArgValue = Union[
98
+ Expression,
99
+ QuantumOperand,
100
+ SlicedHandleBinding,
101
+ SubscriptHandleBinding,
102
+ HandleBinding,
103
+ ]
112
104
 
113
105
 
114
106
  class OperandIdentifier(BaseModel):
@@ -121,13 +113,6 @@ class QuantumFunctionCall(QuantumOperation):
121
113
  description="The function that is called"
122
114
  )
123
115
  params: Dict[str, Expression] = pydantic.Field(default_factory=dict)
124
- release_by_inverse: bool = pydantic.Field(
125
- default=False, description="Release zero inputs in inverse call."
126
- )
127
- should_control: bool = pydantic.Field(
128
- default=True,
129
- description="False value indicates this call shouldn't be controlled even if the flow is controlled.",
130
- )
131
116
  inputs: Dict[str, HandleBinding] = pydantic.Field(
132
117
  default_factory=dict,
133
118
  description="A mapping from the input name to the wire it connects to",
@@ -142,12 +127,7 @@ class QuantumFunctionCall(QuantumOperation):
142
127
  default_factory=dict,
143
128
  description="A mapping from the output name to the wire it connects to",
144
129
  )
145
- name: PydanticNonEmptyString = pydantic.Field(
146
- default=None,
147
- description="The name of the function instance. "
148
- "If not set, determined automatically.",
149
- )
150
- operands: Dict[str, "QuantumOperand"] = pydantic.Field(
130
+ operands: Dict[str, QuantumOperand] = pydantic.Field(
151
131
  description="Function calls passed to the operator",
152
132
  default_factory=dict,
153
133
  )
@@ -157,8 +137,8 @@ class QuantumFunctionCall(QuantumOperation):
157
137
  default=None
158
138
  )
159
139
 
160
- _operator_synthesis_data: OperatorSynthesisData = pydantic.PrivateAttr(
161
- default_factory=OperatorSynthesisData
140
+ _synthesis_data: CallSynthesisData = pydantic.PrivateAttr(
141
+ default_factory=CallSynthesisData
162
142
  )
163
143
 
164
144
  @property
@@ -207,33 +187,6 @@ class QuantumFunctionCall(QuantumOperation):
207
187
  result.extend(self.outputs.values())
208
188
  return result
209
189
 
210
- def __eq__(self, other: Any) -> bool:
211
- return isinstance(other, QuantumFunctionCall) and self.name == other.name
212
-
213
- def __hash__(self) -> int:
214
- return hash(self.name)
215
-
216
- @pydantic.validator("name", pre=True, always=True)
217
- def _create_name(cls, name: Optional[str], values: Dict[str, Any]) -> str:
218
- """
219
- generates a name to a user defined-functions as follows:
220
- <function_name>_<SUFFIX_MARKER>_<random_suffix>
221
- """
222
- if name is not None:
223
- match = re.fullmatch(pattern=NAME_REGEX, string=name)
224
- if match is None:
225
- raise ValueError(BAD_CALL_NAME_ERROR_MSG)
226
- return name
227
-
228
- function = values.get("function")
229
- if isinstance(function, OperandIdentifier):
230
- function = function.name
231
-
232
- suffix = f"{SUFFIX_MARKER}_{randomize_suffix()}"
233
- if not function:
234
- return name if name else suffix
235
- return f"{function}_{suffix}"
236
-
237
190
  @property
238
191
  def pos_param_args(self) -> Dict[str, Expression]:
239
192
  return dict(
@@ -324,17 +277,11 @@ class QuantumFunctionCall(QuantumOperation):
324
277
  qlambda.set_op_decl(op_decl)
325
278
 
326
279
  @property
327
- def operator_synthesis_data(self) -> OperatorSynthesisData:
328
- return self._operator_synthesis_data
329
-
330
- def set_operator_synthesis_data(
331
- self, operator_synthesis_data: OperatorSynthesisData
332
- ) -> None:
333
- self._operator_synthesis_data = operator_synthesis_data
280
+ def synthesis_data(self) -> CallSynthesisData:
281
+ return self._synthesis_data
334
282
 
335
- @staticmethod
336
- def _has_repetitions(name_list: Sequence[str]) -> bool:
337
- return len(set(name_list)) < len(name_list)
283
+ def merge_synthesis_data(self, other: CallSynthesisData) -> None:
284
+ self._synthesis_data = self._synthesis_data.merge(other)
338
285
 
339
286
  @pydantic.root_validator()
340
287
  def validate_handles(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@@ -349,67 +296,6 @@ class QuantumFunctionCall(QuantumOperation):
349
296
  return values
350
297
 
351
298
 
352
- ConcreteQuantumStatement = Union[
353
- QuantumFunctionCall,
354
- ArithmeticOperation,
355
- AmplitudeLoadingOperation,
356
- VariableDeclarationStatement,
357
- BindOperation,
358
- NumericReinterpretationOperation,
359
- InplaceBinaryOperation,
360
- QuantumIfOperation,
361
- ]
362
-
363
-
364
- class QuantumLambdaFunction(BaseModel):
365
- """
366
- The definition of an anonymous function passed as operand to higher-level functions
367
- """
368
-
369
- rename_params: Dict[str, str] = pydantic.Field(
370
- default_factory=dict,
371
- description="Mapping of the declared param to the actual variable name used ",
372
- )
373
-
374
- body: List[ConcreteQuantumStatement] = pydantic.Field(
375
- description="A list of function calls passed to the operator"
376
- )
377
-
378
- _func_decl: Optional[QuantumOperandDeclaration] = pydantic.PrivateAttr(default=None)
379
-
380
- @property
381
- def func_decl(self) -> Optional[QuantumOperandDeclaration]:
382
- return self._func_decl
383
-
384
- def set_op_decl(self, fd: QuantumOperandDeclaration) -> None:
385
- self._func_decl = fd
386
-
387
-
388
- class LambdaListComprehension(BaseModel):
389
- """
390
- Specification of a list of lambda functions iteratively
391
- """
392
-
393
- count: Expression = pydantic.Field(
394
- description="The number of lambda functions in the list"
395
- )
396
-
397
- index_var: str = pydantic.Field(
398
- description="The name of the integer variable holding the iteration index"
399
- )
400
-
401
- func: QuantumLambdaFunction = pydantic.Field(
402
- description="A lambda function definition replicated for index values 0 to count-1"
403
- )
404
-
405
-
406
- QuantumCallable = Union[str, QuantumLambdaFunction]
407
- QuantumOperand = Union[QuantumCallable, List[QuantumCallable], LambdaListComprehension]
408
-
409
- QuantumFunctionCall.update_forward_refs()
410
- QuantumIfOperation.update_forward_refs(QuantumOperand=QuantumOperand)
411
-
412
-
413
299
  def get_lambda_defs(operand: QuantumOperand) -> List[QuantumCallable]:
414
300
  if isinstance(operand, list):
415
301
  return operand
@@ -108,6 +108,14 @@ class QuantumFunctionDeclaration(FunctionDeclaration):
108
108
  ) -> None:
109
109
  pass
110
110
 
111
+ @property
112
+ def port_names(self) -> List[str]:
113
+ return list(self.port_declarations.keys())
114
+
115
+ @property
116
+ def operand_names(self) -> List[str]:
117
+ return list(self.operand_declarations.keys())
118
+
111
119
  def ports_by_direction(
112
120
  self, direction: PortDirection
113
121
  ) -> Mapping[str, PortDeclaration]:
@@ -5,7 +5,7 @@ from sympy import Equality
5
5
  from sympy.core.numbers import Integer
6
6
 
7
7
  from classiq.interface.generator.expressions.expression import Expression
8
- from classiq.interface.generator.expressions.qmod_qnum_proxy import QmodQNumProxy
8
+ from classiq.interface.generator.expressions.qmod_qscalar_proxy import QmodQNumProxy
9
9
  from classiq.interface.model.quantum_expressions.control_state import (
10
10
  min_bit_length,
11
11
  to_twos_complement,
@@ -17,8 +17,7 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
17
17
  from classiq.exceptions import ClassiqValueError
18
18
 
19
19
  if TYPE_CHECKING:
20
- from classiq.interface.model.quantum_function_call import QuantumOperand
21
-
20
+ from classiq.interface.model.quantum_lambda_function import QuantumOperand
22
21
 
23
22
  QUANTUM_IF_INOUT_NAME = "ctrl"
24
23
  QUANTUM_IF_CONDITION_ARG_ERROR_MESSAGE_FORMAT = (
@@ -0,0 +1,64 @@
1
+ from typing import TYPE_CHECKING, Dict, List, Optional, Union
2
+
3
+ import pydantic
4
+ from pydantic import BaseModel
5
+
6
+ from classiq.interface.generator.expressions.expression import Expression
7
+ from classiq.interface.model.quantum_function_declaration import (
8
+ QuantumOperandDeclaration,
9
+ )
10
+ from classiq.interface.model.quantum_if_operation import QuantumIfOperation
11
+
12
+ if TYPE_CHECKING:
13
+ from classiq.interface.model.statement_block import StatementBlock
14
+
15
+ from classiq.interface.model.within_apply_operation import WithinApplyOperation
16
+
17
+
18
+ class QuantumLambdaFunction(BaseModel):
19
+ """
20
+ The definition of an anonymous function passed as operand to higher-level functions
21
+ """
22
+
23
+ rename_params: Dict[str, str] = pydantic.Field(
24
+ default_factory=dict,
25
+ description="Mapping of the declared param to the actual variable name used ",
26
+ )
27
+
28
+ body: "StatementBlock" = pydantic.Field(
29
+ description="A list of function calls passed to the operator"
30
+ )
31
+
32
+ _func_decl: Optional[QuantumOperandDeclaration] = pydantic.PrivateAttr(default=None)
33
+
34
+ @property
35
+ def func_decl(self) -> Optional[QuantumOperandDeclaration]:
36
+ return self._func_decl
37
+
38
+ def set_op_decl(self, fd: QuantumOperandDeclaration) -> None:
39
+ self._func_decl = fd
40
+
41
+
42
+ class LambdaListComprehension(BaseModel):
43
+ """
44
+ Specification of a list of lambda functions iteratively
45
+ """
46
+
47
+ count: Expression = pydantic.Field(
48
+ description="The number of lambda functions in the list"
49
+ )
50
+
51
+ index_var: str = pydantic.Field(
52
+ description="The name of the integer variable holding the iteration index"
53
+ )
54
+
55
+ func: QuantumLambdaFunction = pydantic.Field(
56
+ description="A lambda function definition replicated for index values 0 to count-1"
57
+ )
58
+
59
+
60
+ QuantumCallable = Union[str, QuantumLambdaFunction]
61
+ QuantumOperand = Union[QuantumCallable, List[QuantumCallable], LambdaListComprehension]
62
+
63
+ QuantumIfOperation.update_forward_refs(QuantumOperand=QuantumOperand)
64
+ WithinApplyOperation.update_forward_refs(QuantumOperand=QuantumOperand)
@@ -1,13 +1,19 @@
1
1
  from typing import Any, Dict, Literal, Optional, Union
2
2
 
3
3
  import pydantic
4
- from pydantic import Extra
4
+ from pydantic import Extra, Field
5
+ from typing_extensions import Annotated
5
6
 
6
7
  from classiq.interface.generator.arith.register_user_input import (
7
8
  RegisterArithmeticInfo,
8
9
  RegisterUserInput,
9
10
  )
10
11
  from classiq.interface.generator.expressions.expression import Expression
12
+ from classiq.interface.generator.expressions.qmod_qscalar_proxy import (
13
+ QmodQNumProxy,
14
+ QmodQScalarProxy,
15
+ )
16
+ from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
11
17
  from classiq.interface.helpers.hashable_pydantic_base_model import (
12
18
  HashablePydanticBaseModel,
13
19
  )
@@ -40,8 +46,16 @@ class QuantumType(HashablePydanticBaseModel):
40
46
  def set_size_in_bits(self, val: int) -> None:
41
47
  self._size_in_bits = val
42
48
 
49
+ def get_proxy(self, name: str) -> QmodSizedProxy:
50
+ return QmodSizedProxy(size=self.size_in_bits)
51
+
52
+
53
+ class QuantumScalar(QuantumType):
54
+ def get_proxy(self, name: str) -> QmodQScalarProxy:
55
+ return QmodQScalarProxy(name, size=self.size_in_bits)
56
+
43
57
 
44
- class QuantumBit(QuantumType):
58
+ class QuantumBit(QuantumScalar):
45
59
  kind: Literal["qbit"]
46
60
 
47
61
  def __init__(self, **kwargs: Any) -> None:
@@ -69,83 +83,69 @@ class QuantumBitvector(QuantumArray):
69
83
  self._size_in_bits = self.length.to_int_value()
70
84
 
71
85
 
72
- class QuantumNumeric(QuantumType):
86
+ class QuantumNumeric(QuantumScalar):
87
+ kind: Literal["qnum"]
88
+
73
89
  size: Optional[Expression] = pydantic.Field()
74
- kind: str = pydantic.Field()
90
+ is_signed: Optional[Expression] = pydantic.Field()
91
+ fraction_digits: Optional[Expression] = pydantic.Field()
75
92
 
76
93
  @pydantic.root_validator(pre=True)
77
94
  def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
78
95
  return values_with_discriminator(values, "kind", "qnum")
79
96
 
80
- _is_signed: bool = pydantic.PrivateAttr(default=False)
81
-
82
- _fraction_digits: int = pydantic.PrivateAttr(default=0)
97
+ @pydantic.root_validator
98
+ def _validate_fields(cls, values: Dict[str, Any]) -> Dict[str, Any]:
99
+ has_sign = values["is_signed"] is not None
100
+ has_fraction_digits = values["fraction_digits"] is not None
101
+ if has_sign and not has_fraction_digits or not has_sign and has_fraction_digits:
102
+ raise ClassiqValueError(
103
+ "Assign neither or both of is_signed and fraction_digits"
104
+ )
105
+ return values
83
106
 
84
107
  @property
85
- def size_in_bits_expr(self) -> Optional[Expression]:
86
- return self.size
108
+ def has_sign(self) -> bool:
109
+ return self.is_signed is not None
87
110
 
88
111
  @property
89
- def is_signed(self) -> bool:
90
- return self._is_signed
91
-
92
- def set_signed(self, val: bool) -> None:
93
- self._is_signed = val
112
+ def sign_value(self) -> bool:
113
+ return False if self.is_signed is None else self.is_signed.to_bool_value()
94
114
 
95
115
  @property
96
- def fraction_digits(self) -> int:
97
- return self._fraction_digits
116
+ def has_fraction_digits(self) -> bool:
117
+ return self.fraction_digits is not None
98
118
 
99
- def set_fraction_digits(self, val: int) -> None:
100
- self._fraction_digits = val
119
+ @property
120
+ def fraction_digits_value(self) -> int:
121
+ return (
122
+ 0 if self.fraction_digits is None else self.fraction_digits.to_int_value()
123
+ )
101
124
 
102
125
  def _update_size_in_bits_from_declaration(self) -> None:
103
126
  if self.size is not None and self.size.is_evaluated():
104
127
  self._size_in_bits = self.size.to_int_value()
105
128
 
106
-
107
- class QuantumInteger(QuantumNumeric):
108
- kind: Literal["qint"]
109
-
110
- @pydantic.root_validator(pre=True)
111
- def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
112
- return values_with_discriminator(values, "kind", "qint")
113
-
114
-
115
- class QuantumFixedReal(QuantumNumeric):
116
- fraction_places: Expression = pydantic.Field()
117
-
118
- kind: Literal["qfixed"]
119
-
120
- @pydantic.root_validator(pre=True)
121
- def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
122
- return values_with_discriminator(values, "kind", "qfixed")
123
-
124
- @property
125
- def fraction_digits(self) -> int:
126
- return self.fraction_places.to_int_value()
127
-
128
- def set_fraction_digits(self, val: int) -> None:
129
- if val != self.fraction_places.to_int_value():
130
- raise ClassiqValueError(
131
- "Cannot assign value of fixed-point number with incompatible fraction digits"
132
- )
129
+ def get_proxy(self, name: str) -> QmodQNumProxy:
130
+ return QmodQNumProxy(
131
+ name,
132
+ size=self.size_in_bits,
133
+ fraction_digits=self.fraction_digits_value,
134
+ is_signed=self.sign_value,
135
+ )
133
136
 
134
137
 
135
- ConcreteQuantumType = Union[
136
- QuantumBit,
137
- QuantumBitvector,
138
- QuantumNumeric,
139
- QuantumInteger,
140
- QuantumFixedReal,
138
+ ConcreteQuantumType = Annotated[
139
+ Union[QuantumBit, QuantumBitvector, QuantumNumeric],
140
+ Field(discriminator="kind", default_factory=QuantumBitvector),
141
141
  ]
142
142
 
143
143
 
144
144
  def register_info_to_quantum_type(reg_info: RegisterArithmeticInfo) -> QuantumNumeric:
145
145
  result = QuantumNumeric()
146
146
  result.set_size_in_bits(reg_info.size)
147
- result.set_signed(reg_info.is_signed)
148
- result.set_fraction_digits(reg_info.fraction_places)
147
+ result.is_signed = Expression(expr=str(reg_info.is_signed))
148
+ result.fraction_digits = Expression(expr=str(reg_info.fraction_places))
149
149
  return result
150
150
 
151
151
 
@@ -153,10 +153,11 @@ UNRESOLVED_SIZE = 1000
153
153
 
154
154
 
155
155
  def quantum_var_to_register(name: str, qtype: QuantumType) -> RegisterUserInput:
156
- signed = qtype.is_signed if isinstance(qtype, QuantumNumeric) else False
157
- if isinstance(qtype, (QuantumFixedReal, QuantumNumeric)):
158
- fraction_places = qtype.fraction_digits
156
+ if isinstance(qtype, QuantumNumeric):
157
+ signed = qtype.sign_value
158
+ fraction_places = qtype.fraction_digits_value
159
159
  else:
160
+ signed = False
160
161
  fraction_places = 0
161
162
  return RegisterUserInput(
162
163
  name=name,
@@ -13,7 +13,7 @@ from classiq.interface.model.quantum_type import (
13
13
 
14
14
  class QuantumVariableDeclaration(BaseModel):
15
15
  name: str
16
- quantum_type: ConcreteQuantumType = pydantic.Field(default_factory=QuantumBitvector)
16
+ quantum_type: ConcreteQuantumType
17
17
  size: Optional[Expression] = pydantic.Field(default=None)
18
18
 
19
19
  @pydantic.validator("size")
@@ -0,0 +1,32 @@
1
+ from typing import List, Union
2
+
3
+ from classiq.interface.model.bind_operation import BindOperation
4
+ from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
5
+ from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
6
+ AmplitudeLoadingOperation,
7
+ )
8
+ from classiq.interface.model.quantum_expressions.arithmetic_operation import (
9
+ ArithmeticOperation,
10
+ )
11
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
12
+ from classiq.interface.model.quantum_if_operation import QuantumIfOperation
13
+ from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
14
+ from classiq.interface.model.variable_declaration_statement import (
15
+ VariableDeclarationStatement,
16
+ )
17
+ from classiq.interface.model.within_apply_operation import WithinApplyOperation
18
+
19
+ ConcreteQuantumStatement = Union[
20
+ QuantumFunctionCall,
21
+ ArithmeticOperation,
22
+ AmplitudeLoadingOperation,
23
+ VariableDeclarationStatement,
24
+ BindOperation,
25
+ InplaceBinaryOperation,
26
+ QuantumIfOperation,
27
+ WithinApplyOperation,
28
+ ]
29
+
30
+ StatementBlock = List[ConcreteQuantumStatement]
31
+
32
+ QuantumLambdaFunction.update_forward_refs(StatementBlock=StatementBlock)
@@ -2,8 +2,7 @@ from typing import Dict, Mapping, Set, Union
2
2
 
3
3
  from classiq.interface.generator.function_params import PortDirection
4
4
  from classiq.interface.generator.functions.core_lib_declarations.quantum_operators import (
5
- APPLY,
6
- OPERAND_FIELD_NAME,
5
+ APPLY_OPERATOR,
7
6
  )
8
7
  from classiq.interface.model.handle_binding import (
9
8
  HandleBinding,
@@ -11,9 +10,10 @@ from classiq.interface.model.handle_binding import (
11
10
  SubscriptHandleBinding,
12
11
  )
13
12
  from classiq.interface.model.port_declaration import PortDeclaration
14
- from classiq.interface.model.quantum_function_call import (
15
- QuantumFunctionCall,
13
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
14
+ from classiq.interface.model.quantum_lambda_function import (
16
15
  QuantumLambdaFunction,
16
+ QuantumOperand,
17
17
  )
18
18
  from classiq.interface.model.quantum_statement import QuantumOperation
19
19
  from classiq.interface.model.validation_handle import HandleState, ValidationHandle
@@ -23,6 +23,7 @@ from classiq.interface.model.validations.handle_validation_base import (
23
23
  from classiq.interface.model.variable_declaration_statement import (
24
24
  VariableDeclarationStatement,
25
25
  )
26
+ from classiq.interface.model.within_apply_operation import WithinApplyOperation
26
27
 
27
28
  from classiq.exceptions import ClassiqValueError
28
29
 
@@ -57,12 +58,14 @@ class HandleValidator(HandleValidationBase):
57
58
  def _validation_handles_state(self) -> Mapping[str, ValidationHandle]:
58
59
  return self._handles_to_state
59
60
 
60
- def handle_call(self, call: QuantumOperation) -> None:
61
- if isinstance(call, QuantumFunctionCall) and call.function == APPLY.name:
62
- self._handle_apply(call)
63
- self._handle_inputs(call.wiring_inputs)
64
- self._handle_outputs(call.wiring_outputs)
65
- self._handle_inouts(call.wiring_inouts)
61
+ def handle_operation(self, op: QuantumOperation) -> None:
62
+ if isinstance(op, QuantumFunctionCall) and op.function == APPLY_OPERATOR.name:
63
+ self._handle_apply(op.operands[APPLY_OPERATOR.operand_names[0]])
64
+ elif isinstance(op, WithinApplyOperation):
65
+ self._handle_apply(op.action)
66
+ self._handle_inputs(op.wiring_inputs)
67
+ self._handle_outputs(op.wiring_outputs)
68
+ self._handle_inouts(op.wiring_inouts)
66
69
 
67
70
  def handle_variable_declaration(
68
71
  self, declaration: VariableDeclarationStatement
@@ -130,8 +133,7 @@ class HandleValidator(HandleValidationBase):
130
133
  f"Invalid use of inout handle {handle!r}, used both in slice or subscript and whole"
131
134
  )
132
135
 
133
- def _handle_apply(self, call: QuantumFunctionCall) -> None:
134
- operand = call.operands[OPERAND_FIELD_NAME]
136
+ def _handle_apply(self, operand: QuantumOperand) -> None:
135
137
  if not isinstance(operand, QuantumLambdaFunction):
136
138
  return
137
139
  local_variables: Set[str] = set()
@@ -0,0 +1,11 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from classiq.interface.model.quantum_statement import QuantumOperation
4
+
5
+ if TYPE_CHECKING:
6
+ from classiq.interface.model.quantum_lambda_function import QuantumOperand
7
+
8
+
9
+ class WithinApplyOperation(QuantumOperation):
10
+ compute: "QuantumOperand"
11
+ action: "QuantumOperand"
@@ -1,10 +1,13 @@
1
+ from typing import Any
2
+
1
3
  import sympy
2
4
  from pyomo.core.base import _GeneralVarData
5
+ from pyomo.core.expr.sympy_tools import PyomoSympyBimap
3
6
 
4
7
 
5
8
  # This code is a pure copy paste from pyomo.core.expr.sympy_tools.PyomoSympyBimap.getSympySymbol
6
9
  # except one line.
7
- def get_sympy_symbol(self, pyomo_object):
10
+ def get_sympy_symbol(self: PyomoSympyBimap, pyomo_object: Any) -> sympy.Symbol:
8
11
  if pyomo_object in self.pyomo2sympy:
9
12
  return self.pyomo2sympy[pyomo_object]
10
13
  # Pyomo currently ONLY supports Real variables (not complex
@@ -44,6 +44,11 @@ TASKS_SOLVE_SUFFIX = "/tasks/solve"
44
44
  MODEL_GENERATE_PREFIX = "/generate_model"
45
45
  CHEMISTRY_GENERATE_MODEL_PATH = MODEL_GENERATE_PREFIX + "/chemistry"
46
46
 
47
+ CHEMISTRY_QMOD_PATH = "/generate_model/chemistry/qmod"
48
+ GROVER_QMOD_PATH = "/generate_model/grover/qmod"
49
+ FINANCE_QMOD_PATH = "/generate_model/finance/qmod"
50
+
51
+
47
52
  TASK_TRAIN_SUFFIX = TASKS_SUFFIX + "/train"
48
53
  TASK_TEST_SUFFIX = TASKS_SUFFIX + "/test"
49
54
  TASK_PREDICT_SUFFIX = TASKS_SUFFIX + "/predict"