classiq 0.51.1__py3-none-any.whl → 0.53.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 (158) hide show
  1. classiq/_internals/api_wrapper.py +47 -15
  2. classiq/_internals/authentication/auth0.py +20 -4
  3. classiq/_internals/authentication/password_manager.py +16 -4
  4. classiq/_internals/client.py +3 -3
  5. classiq/_internals/host_checker.py +5 -3
  6. classiq/_internals/jobs.py +3 -3
  7. classiq/analyzer/analyzer_utilities.py +1 -1
  8. classiq/applications/chemistry/ground_state_problem.py +1 -1
  9. classiq/applications/combinatorial_helpers/pyomo_utils.py +3 -1
  10. classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
  11. classiq/applications/qnn/qlayer.py +25 -6
  12. classiq/execution/__init__.py +5 -0
  13. classiq/execution/execution_session.py +43 -2
  14. classiq/execution/iqcc.py +63 -0
  15. classiq/execution/jobs.py +2 -2
  16. classiq/execution/qaoa.py +84 -0
  17. classiq/executor.py +3 -3
  18. classiq/interface/_version.py +1 -1
  19. classiq/interface/analyzer/analysis_params.py +19 -9
  20. classiq/interface/analyzer/cytoscape_graph.py +10 -3
  21. classiq/interface/analyzer/result.py +6 -5
  22. classiq/interface/applications/qsvm.py +13 -12
  23. classiq/interface/backend/backend_preferences.py +78 -105
  24. classiq/interface/backend/ionq/ionq_quantum_program.py +12 -19
  25. classiq/interface/backend/pydantic_backend.py +24 -12
  26. classiq/interface/backend/quantum_backend_providers.py +2 -0
  27. classiq/interface/chemistry/fermionic_operator.py +7 -7
  28. classiq/interface/chemistry/ground_state_problem.py +23 -18
  29. classiq/interface/chemistry/molecule.py +10 -5
  30. classiq/interface/chemistry/operator.py +71 -44
  31. classiq/interface/combinatorial_optimization/mht_qaoa_input.py +2 -1
  32. classiq/interface/debug_info/debug_info.py +3 -4
  33. classiq/interface/exceptions.py +3 -1
  34. classiq/interface/execution/iqcc.py +19 -0
  35. classiq/interface/execution/jobs.py +10 -10
  36. classiq/interface/executor/aws_execution_cost.py +37 -20
  37. classiq/interface/executor/execution_preferences.py +1 -2
  38. classiq/interface/executor/execution_request.py +2 -2
  39. classiq/interface/executor/execution_result.py +4 -2
  40. classiq/interface/executor/iqae_result.py +1 -1
  41. classiq/interface/executor/optimizer_preferences.py +14 -10
  42. classiq/interface/executor/quantum_code.py +21 -16
  43. classiq/interface/executor/register_initialization.py +10 -10
  44. classiq/interface/executor/result.py +31 -17
  45. classiq/interface/executor/vqe_result.py +1 -1
  46. classiq/interface/finance/function_input.py +27 -18
  47. classiq/interface/finance/log_normal_model_input.py +2 -2
  48. classiq/interface/finance/model_input.py +3 -2
  49. classiq/interface/generator/amplitude_loading.py +8 -6
  50. classiq/interface/generator/arith/argument_utils.py +24 -0
  51. classiq/interface/generator/arith/arithmetic.py +5 -3
  52. classiq/interface/generator/arith/arithmetic_expression_abc.py +36 -14
  53. classiq/interface/generator/arith/arithmetic_operations.py +6 -3
  54. classiq/interface/generator/arith/binary_ops.py +88 -63
  55. classiq/interface/generator/arith/extremum_operations.py +22 -13
  56. classiq/interface/generator/arith/logical_ops.py +6 -4
  57. classiq/interface/generator/arith/number_utils.py +3 -3
  58. classiq/interface/generator/arith/register_user_input.py +32 -17
  59. classiq/interface/generator/arith/unary_ops.py +5 -4
  60. classiq/interface/generator/chemistry_function_params.py +2 -1
  61. classiq/interface/generator/circuit_code/circuit_code.py +2 -1
  62. classiq/interface/generator/commuting_pauli_exponentiation.py +6 -5
  63. classiq/interface/generator/complex_type.py +14 -18
  64. classiq/interface/generator/control_state.py +32 -26
  65. classiq/interface/generator/expressions/expression.py +6 -5
  66. classiq/interface/generator/function_params.py +22 -39
  67. classiq/interface/generator/functions/classical_function_declaration.py +1 -1
  68. classiq/interface/generator/functions/classical_type.py +32 -23
  69. classiq/interface/generator/functions/concrete_types.py +8 -7
  70. classiq/interface/generator/functions/function_declaration.py +4 -5
  71. classiq/interface/generator/functions/type_name.py +5 -4
  72. classiq/interface/generator/generated_circuit_data.py +9 -6
  73. classiq/interface/generator/grover_diffuser.py +26 -18
  74. classiq/interface/generator/grover_operator.py +32 -22
  75. classiq/interface/generator/hamiltonian_evolution/exponentiation.py +3 -4
  76. classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
  77. classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +8 -7
  78. classiq/interface/generator/hardware/hardware_data.py +27 -26
  79. classiq/interface/generator/hardware_efficient_ansatz.py +11 -6
  80. classiq/interface/generator/hartree_fock.py +2 -1
  81. classiq/interface/generator/identity.py +7 -2
  82. classiq/interface/generator/linear_pauli_rotations.py +27 -14
  83. classiq/interface/generator/mcu.py +15 -12
  84. classiq/interface/generator/mcx.py +18 -10
  85. classiq/interface/generator/model/constraints.py +4 -2
  86. classiq/interface/generator/model/model.py +2 -1
  87. classiq/interface/generator/model/preferences/preferences.py +30 -32
  88. classiq/interface/generator/oracles/custom_oracle.py +13 -10
  89. classiq/interface/generator/piecewise_linear_amplitude_loading.py +37 -21
  90. classiq/interface/generator/qpe.py +38 -26
  91. classiq/interface/generator/qsvm.py +4 -4
  92. classiq/interface/generator/quantum_function_call.py +57 -44
  93. classiq/interface/generator/quantum_program.py +8 -6
  94. classiq/interface/generator/range_types.py +10 -11
  95. classiq/interface/generator/standard_gates/controlled_standard_gates.py +9 -5
  96. classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
  97. classiq/interface/generator/standard_gates/u_gate.py +7 -10
  98. classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
  99. classiq/interface/generator/state_preparation/distributions.py +12 -12
  100. classiq/interface/generator/state_preparation/state_preparation.py +22 -16
  101. classiq/interface/generator/types/enum_declaration.py +2 -1
  102. classiq/interface/generator/ucc.py +2 -1
  103. classiq/interface/generator/unitary_gate.py +2 -1
  104. classiq/interface/generator/user_defined_function_params.py +3 -0
  105. classiq/interface/generator/visitor.py +1 -1
  106. classiq/interface/hardware.py +18 -3
  107. classiq/interface/helpers/custom_pydantic_types.py +38 -47
  108. classiq/interface/helpers/dotdict.py +18 -0
  109. classiq/interface/helpers/pydantic_model_helpers.py +3 -2
  110. classiq/interface/helpers/versioned_model.py +1 -4
  111. classiq/interface/ide/ide_data.py +5 -5
  112. classiq/interface/ide/visual_model.py +18 -5
  113. classiq/interface/interface_version.py +1 -1
  114. classiq/interface/jobs.py +12 -22
  115. classiq/interface/model/bind_operation.py +2 -1
  116. classiq/interface/model/classical_parameter_declaration.py +10 -4
  117. classiq/interface/model/handle_binding.py +20 -24
  118. classiq/interface/model/inplace_binary_operation.py +16 -9
  119. classiq/interface/model/model.py +21 -11
  120. classiq/interface/model/native_function_definition.py +10 -0
  121. classiq/interface/model/port_declaration.py +10 -7
  122. classiq/interface/model/quantum_expressions/arithmetic_operation.py +6 -4
  123. classiq/interface/model/quantum_function_declaration.py +22 -11
  124. classiq/interface/model/quantum_statement.py +6 -7
  125. classiq/interface/model/quantum_type.py +22 -19
  126. classiq/interface/model/statement_block.py +9 -9
  127. classiq/interface/server/global_versions.py +4 -5
  128. classiq/interface/server/routes.py +8 -0
  129. classiq/model_expansions/evaluators/parameter_types.py +3 -3
  130. classiq/model_expansions/expression_renamer.py +1 -1
  131. classiq/model_expansions/quantum_operations/control.py +11 -12
  132. classiq/model_expansions/quantum_operations/emitter.py +22 -0
  133. classiq/model_expansions/quantum_operations/expression_operation.py +2 -20
  134. classiq/model_expansions/quantum_operations/inplace_binary_operation.py +42 -12
  135. classiq/model_expansions/quantum_operations/invert.py +1 -1
  136. classiq/model_expansions/quantum_operations/phase.py +4 -5
  137. classiq/model_expansions/quantum_operations/power.py +1 -1
  138. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +50 -9
  139. classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
  140. classiq/model_expansions/quantum_operations/within_apply.py +1 -1
  141. classiq/qmod/__init__.py +2 -0
  142. classiq/qmod/builtins/__init__.py +1 -3
  143. classiq/qmod/builtins/functions/__init__.py +9 -0
  144. classiq/qmod/builtins/functions/arithmetic.py +10 -0
  145. classiq/qmod/builtins/functions/standard_gates.py +14 -14
  146. classiq/qmod/builtins/functions/variational.py +37 -0
  147. classiq/qmod/create_model_function.py +16 -6
  148. classiq/qmod/qmod_parameter.py +3 -1
  149. classiq/qmod/quantum_expandable.py +43 -10
  150. classiq/qmod/quantum_function.py +24 -2
  151. classiq/qmod/semantics/static_semantics_visitor.py +3 -1
  152. classiq/qmod/synthesize_separately.py +16 -0
  153. classiq/qmod/type_attribute_remover.py +1 -1
  154. classiq/qmod/write_qmod.py +2 -4
  155. classiq/synthesis.py +11 -13
  156. {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/METADATA +3 -2
  157. {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/RECORD +158 -152
  158. {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/WHEEL +0 -0
@@ -405,7 +405,7 @@ def RZZ(theta: CReal, target: QArray[QBit, Literal[2]]) -> None:
405
405
 
406
406
 
407
407
  @qfunc(external=True)
408
- def CH(control: QBit, target: QBit) -> None:
408
+ def CH(ctrl: QBit, target: QBit) -> None:
409
409
  """
410
410
  [Qmod core-library function]
411
411
 
@@ -423,7 +423,7 @@ def CH(control: QBit, target: QBit) -> None:
423
423
  $$
424
424
 
425
425
  Args:
426
- control: The control qubit.
426
+ ctrl: The control qubit.
427
427
  target: The qubit to apply the Hadamard gate on.
428
428
 
429
429
  Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
@@ -432,7 +432,7 @@ def CH(control: QBit, target: QBit) -> None:
432
432
 
433
433
 
434
434
  @qfunc(external=True)
435
- def CX(control: QBit, target: QBit) -> None:
435
+ def CX(ctrl: QBit, target: QBit) -> None:
436
436
  """
437
437
  [Qmod core-library function]
438
438
 
@@ -450,7 +450,7 @@ def CX(control: QBit, target: QBit) -> None:
450
450
  $$
451
451
 
452
452
  Args:
453
- control: The control qubit.
453
+ ctrl: The control qubit.
454
454
  target: The qubit to apply the Pauli-X gate on.
455
455
 
456
456
  Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
@@ -459,7 +459,7 @@ def CX(control: QBit, target: QBit) -> None:
459
459
 
460
460
 
461
461
  @qfunc(external=True)
462
- def CY(control: QBit, target: QBit) -> None:
462
+ def CY(ctrl: QBit, target: QBit) -> None:
463
463
  """
464
464
  [Qmod core-library function]
465
465
 
@@ -477,7 +477,7 @@ def CY(control: QBit, target: QBit) -> None:
477
477
  $$
478
478
 
479
479
  Args:
480
- control: The control qubit.
480
+ ctrl: The control qubit.
481
481
  target: The qubit to apply the Pauli-Y gate on.
482
482
 
483
483
  Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
@@ -486,7 +486,7 @@ def CY(control: QBit, target: QBit) -> None:
486
486
 
487
487
 
488
488
  @qfunc(external=True)
489
- def CZ(control: QBit, target: QBit) -> None:
489
+ def CZ(ctrl: QBit, target: QBit) -> None:
490
490
  """
491
491
  [Qmod core-library function]
492
492
 
@@ -504,7 +504,7 @@ def CZ(control: QBit, target: QBit) -> None:
504
504
  $$
505
505
 
506
506
  Args:
507
- control: The control qubit.
507
+ ctrl: The control qubit.
508
508
  target: The qubit to apply the Pauli-Z gate on.
509
509
 
510
510
  Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
@@ -513,7 +513,7 @@ def CZ(control: QBit, target: QBit) -> None:
513
513
 
514
514
 
515
515
  @qfunc(external=True)
516
- def CRX(theta: CReal, control: QBit, target: QBit) -> None:
516
+ def CRX(theta: CReal, ctrl: QBit, target: QBit) -> None:
517
517
  """
518
518
  [Qmod core-library function]
519
519
 
@@ -532,7 +532,7 @@ def CRX(theta: CReal, control: QBit, target: QBit) -> None:
532
532
 
533
533
  Args:
534
534
  theta: The rotation angle in radians.
535
- control: The control qubit.
535
+ ctrl: The control qubit.
536
536
  target: The qubit to apply the RX gate on.
537
537
 
538
538
  Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
@@ -541,7 +541,7 @@ def CRX(theta: CReal, control: QBit, target: QBit) -> None:
541
541
 
542
542
 
543
543
  @qfunc(external=True)
544
- def CRY(theta: CReal, control: QBit, target: QBit) -> None:
544
+ def CRY(theta: CReal, ctrl: QBit, target: QBit) -> None:
545
545
  """
546
546
  [Qmod core-library function]
547
547
 
@@ -569,7 +569,7 @@ def CRY(theta: CReal, control: QBit, target: QBit) -> None:
569
569
 
570
570
 
571
571
  @qfunc(external=True)
572
- def CRZ(theta: CReal, control: QBit, target: QBit) -> None:
572
+ def CRZ(theta: CReal, ctrl: QBit, target: QBit) -> None:
573
573
  """
574
574
  [Qmod core-library function]
575
575
 
@@ -597,7 +597,7 @@ def CRZ(theta: CReal, control: QBit, target: QBit) -> None:
597
597
 
598
598
 
599
599
  @qfunc(external=True)
600
- def CPHASE(theta: CReal, control: QBit, target: QBit) -> None:
600
+ def CPHASE(theta: CReal, ctrl: QBit, target: QBit) -> None:
601
601
  """
602
602
  [Qmod core-library function]
603
603
 
@@ -707,7 +707,7 @@ def U(theta: CReal, phi: CReal, lam: CReal, gam: CReal, target: QBit) -> None:
707
707
 
708
708
 
709
709
  @qfunc(external=True)
710
- def CCX(control: QArray[QBit, Literal[2]], target: QBit) -> None:
710
+ def CCX(ctrl: QArray[QBit, Literal[2]], target: QBit) -> None:
711
711
  """
712
712
  [Qmod core-library function]
713
713
 
@@ -0,0 +1,37 @@
1
+ from classiq.qmod.cparam import CReal
2
+ from classiq.qmod.qfunc import qfunc
3
+ from classiq.qmod.qmod_parameter import CArray
4
+ from classiq.qmod.qmod_variable import Output, QArray, QBit
5
+
6
+
7
+ @qfunc(external=True)
8
+ def encode_in_angle(data: CArray[CReal], qba: Output[QArray[QBit]]) -> None:
9
+ """
10
+ [Qmod Classiq-library function]
11
+
12
+ Creates an angle encoding of n data points on n qubits.
13
+
14
+ Applies RY($\\pi$data[i]) on qba[i].
15
+
16
+ Args:
17
+ data: A classical array representing the data to encode.
18
+ qba: The array of qubits on which the data is encoded.
19
+ """
20
+ pass
21
+
22
+
23
+ @qfunc(external=True)
24
+ def encode_on_bloch(data: CArray[CReal], qba: Output[QArray]) -> None:
25
+ """
26
+ [Qmod Classiq-library function]
27
+
28
+ Creates a dense angle encoding of n data points on n//2 qubits.
29
+
30
+ Encodes pairs of data points on a Bloch sphere, via RX($\\pi$data[2*i])RZ($\\pi$data[2*i+1]) on qba[i].
31
+ If the length of the data is odd then RX($\\pi$data[i]) is applied on the last qubit.
32
+
33
+ Args:
34
+ data: A classical array representing the data to encode.
35
+ qba: The QArray of QBits on which the data is encoded.
36
+ """
37
+ pass
@@ -155,9 +155,9 @@ def _get_wrapper_main(gen_main: QFunc, preferences: Optional[Preferences]) -> Mo
155
155
 
156
156
 
157
157
  def _get_all_model_functions_as_generative_functions() -> List[GenerativeQFunc]:
158
+
158
159
  gen_functions = list(GEN_QFUNCS) + [
159
- GenerativeQFunc(dec_func._py_callable, dec_func.func_decl)
160
- for dec_func in DEC_QFUNCS
160
+ _get_gen_from_dec(dec_func) for dec_func in DEC_QFUNCS
161
161
  ]
162
162
  return [
163
163
  (
@@ -165,7 +165,7 @@ def _get_all_model_functions_as_generative_functions() -> List[GenerativeQFunc]:
165
165
  if gen_func.func_decl.name != MAIN_FUNCTION_NAME
166
166
  else GenerativeQFunc(
167
167
  gen_func._py_callable,
168
- gen_func.func_decl.copy(update={"name": GEN_MAIN_NAME}),
168
+ gen_func.func_decl.model_copy(update={"name": GEN_MAIN_NAME}),
169
169
  )
170
170
  )
171
171
  for gen_func in gen_functions
@@ -173,6 +173,16 @@ def _get_all_model_functions_as_generative_functions() -> List[GenerativeQFunc]:
173
173
  ]
174
174
 
175
175
 
176
+ def _get_gen_from_dec(dec_func: QFunc) -> GenerativeQFunc:
177
+ synthesis_data = dec_func.synthesis_data
178
+ if synthesis_data is not None and synthesis_data.should_synthesize_separately:
179
+ raise ClassiqError(
180
+ """The model contains generative functions,
181
+ which cannot coexist with functions marked for separate synthesis"""
182
+ )
183
+ return GenerativeQFunc(dec_func._py_callable, dec_func.func_decl)
184
+
185
+
176
186
  def _interpret_generative_model(
177
187
  gen_model: Model, gen_functions: List[GenerativeQFunc]
178
188
  ) -> Dict[str, NativeFunctionDefinition]:
@@ -188,9 +198,9 @@ def _interpret_generative_model(
188
198
  expanded_gen_main_name = cast(
189
199
  QuantumFunctionCall, functions_dict[MAIN_FUNCTION_NAME].body[0]
190
200
  ).func_name
191
- functions_dict[MAIN_FUNCTION_NAME] = functions_dict[expanded_gen_main_name].copy(
192
- update={"name": MAIN_FUNCTION_NAME}
193
- )
201
+ functions_dict[MAIN_FUNCTION_NAME] = functions_dict[
202
+ expanded_gen_main_name
203
+ ].model_copy(update={"name": MAIN_FUNCTION_NAME})
194
204
  functions_dict.pop(expanded_gen_main_name)
195
205
 
196
206
  return functions_dict
@@ -44,7 +44,9 @@ class CParamList(CParam):
44
44
  self._list_type = list_type
45
45
 
46
46
  def __getitem__(self, key: Any) -> CParam:
47
+ param_type = self._list_type.element_type
47
48
  if isinstance(key, slice):
49
+ param_type = self._list_type
48
50
  start = key.start if key.start is not None else ""
49
51
  stop = key.stop if key.stop is not None else ""
50
52
  if key.step is not None:
@@ -53,7 +55,7 @@ class CParamList(CParam):
53
55
  key = f"{start}:{stop}"
54
56
  return create_param(
55
57
  f"({self})[{key}]",
56
- self._list_type.element_type,
58
+ param_type,
57
59
  qmodule=self._qmodule,
58
60
  )
59
61
 
@@ -1,4 +1,5 @@
1
1
  import inspect
2
+ import warnings
2
3
  from abc import ABC
3
4
  from dataclasses import is_dataclass
4
5
  from enum import Enum as PythonEnum
@@ -17,12 +18,16 @@ from typing import (
17
18
  overload,
18
19
  )
19
20
 
21
+ import pydantic
20
22
  from sympy import Basic
21
23
  from typing_extensions import Self
22
24
 
23
- from classiq.interface.exceptions import ClassiqValueError
25
+ from classiq.interface.exceptions import ClassiqDeprecationWarning, ClassiqValueError
24
26
  from classiq.interface.generator.expressions.expression import Expression
25
- from classiq.interface.generator.functions.concrete_types import PythonClassicalTypes
27
+ from classiq.interface.generator.functions.concrete_types import (
28
+ NativePythonClassicalTypes,
29
+ PythonClassicalPydanticTypes,
30
+ )
26
31
  from classiq.interface.model.classical_parameter_declaration import (
27
32
  AnonClassicalParameterDeclaration,
28
33
  )
@@ -334,15 +339,24 @@ def prepare_arg(
334
339
  def _validate_classical_arg(
335
340
  arg: Any, arg_decl: AnonClassicalParameterDeclaration, func_name: Optional[str]
336
341
  ) -> None:
342
+ is_native_or_compatible_type = not isinstance(
343
+ arg, (*NativePythonClassicalTypes, CParam, SymbolicExpr, Basic, PythonEnum)
344
+ ) and not is_dataclass(
345
+ arg
346
+ ) # type: ignore[unreachable]
347
+ try:
348
+ is_pydantic_classical_type = isinstance(
349
+ arg, pydantic.BaseModel
350
+ ) and not isinstance(arg, PythonClassicalPydanticTypes)
351
+ except ClassiqValueError:
352
+ is_pydantic_classical_type = False
353
+
354
+ is_incompatible_symbolic_expr = isinstance(arg, SymbolicExpr) and arg.is_quantum
355
+
337
356
  if (
338
- not isinstance(
339
- arg, (*PythonClassicalTypes, CParam, SymbolicExpr, Basic, PythonEnum)
340
- )
341
- and not is_dataclass(arg) # type:ignore[unreachable]
342
- or isinstance(arg, SymbolicExpr)
343
- and arg.is_quantum
344
- ):
345
- func_name_message = "" if func_name is None else f" of function {func_name!r}"
357
+ is_native_or_compatible_type or is_pydantic_classical_type
358
+ ) or is_incompatible_symbolic_expr:
359
+ func_name_message = f" of function {func_name!r}" if func_name else ""
346
360
  raise ClassiqValueError(
347
361
  f"Argument {str(arg)!r} to parameter {arg_decl.name!r}{func_name_message} "
348
362
  f"has incompatible type; expected "
@@ -379,6 +393,7 @@ def _get_operand_hint(
379
393
  def _prepare_args(
380
394
  decl: AnonQuantumFunctionDeclaration, arg_list: List[Any], kwargs: Dict[str, Any]
381
395
  ) -> List[ArgValue]:
396
+ _apply_control_backward_compatibility(decl, kwargs)
382
397
  result = []
383
398
  for idx, arg_decl in enumerate(decl.positional_arg_declarations):
384
399
  arg = None
@@ -401,6 +416,24 @@ def _prepare_args(
401
416
  return result
402
417
 
403
418
 
419
+ def _apply_control_backward_compatibility(
420
+ decl: AnonQuantumFunctionDeclaration, kwargs: Dict[str, Any]
421
+ ) -> None:
422
+ from classiq.qmod.builtins.functions import __all__ as builtin_functions
423
+
424
+ if decl.name in builtin_functions and "control" in kwargs:
425
+ warnings.warn(
426
+ f"Parameter 'control' of function {decl.name!r} has been renamed to "
427
+ f"'ctrl'. Parameter 'control' will no longer be supported starting on "
428
+ f"4/11/24 at the earliest.\nHint: Change {decl.name}(control=...) to "
429
+ f"{decl.name}(ctrl=...).",
430
+ ClassiqDeprecationWarning,
431
+ stacklevel=6,
432
+ )
433
+ kwargs["ctrl"] = kwargs["control"]
434
+ kwargs.pop("control")
435
+
436
+
404
437
  def _create_quantum_function_call(
405
438
  decl_: QuantumFunctionDeclaration,
406
439
  index_: Optional[Union[CParamScalar, int]] = None,
@@ -10,7 +10,10 @@ from classiq.interface.executor.execution_preferences import ExecutionPreference
10
10
  from classiq.interface.generator.model.constraints import Constraints
11
11
  from classiq.interface.generator.model.preferences.preferences import Preferences
12
12
  from classiq.interface.model.model import Model
13
- from classiq.interface.model.native_function_definition import NativeFunctionDefinition
13
+ from classiq.interface.model.native_function_definition import (
14
+ FunctionSynthesisData,
15
+ NativeFunctionDefinition,
16
+ )
14
17
  from classiq.interface.model.quantum_function_declaration import (
15
18
  NamedParamsQuantumFunctionDeclaration,
16
19
  )
@@ -32,6 +35,7 @@ class QFunc(QExpandable):
32
35
  _validate_no_gen_params(py_callable.__annotations__)
33
36
  super().__init__(py_callable)
34
37
  functools.update_wrapper(self, py_callable)
38
+ self._synthesis_data: Optional[FunctionSynthesisData] = None
35
39
 
36
40
  @property
37
41
  def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
@@ -40,6 +44,14 @@ class QFunc(QExpandable):
40
44
  infer_func_decl(self._py_callable, qmodule=self._qmodule),
41
45
  )
42
46
 
47
+ @property
48
+ def synthesis_data(self) -> Optional[FunctionSynthesisData]:
49
+ return self._synthesis_data
50
+
51
+ @synthesis_data.setter
52
+ def synthesis_data(self, value: FunctionSynthesisData) -> None:
53
+ self._synthesis_data = value
54
+
43
55
  def __call__(self, *args: Any, **kwargs: Any) -> None:
44
56
  super().__call__(*args, **kwargs)
45
57
  self.expand()
@@ -82,7 +94,17 @@ class QFunc(QExpandable):
82
94
  return
83
95
  super().expand()
84
96
  self._qmodule.native_defs[self.func_decl.name] = NativeFunctionDefinition(
85
- **{**self.func_decl.dict(), **{"body": self.body}}
97
+ **{
98
+ **self.func_decl.model_dump(),
99
+ **{
100
+ "body": self.body,
101
+ "synthesis_data": (
102
+ self.synthesis_data
103
+ if self.synthesis_data is not None
104
+ else FunctionSynthesisData()
105
+ ),
106
+ },
107
+ },
86
108
  )
87
109
 
88
110
  def _add_constants_from_classical_code(
@@ -209,7 +209,9 @@ class StaticSemanticsVisitor(Visitor):
209
209
  **self.current_scope.operands,
210
210
  },
211
211
  )
212
- elif isinstance(op, InplaceBinaryOperation):
212
+ elif isinstance(op, InplaceBinaryOperation) and isinstance(
213
+ op.value, HandleBinding
214
+ ):
213
215
  check_no_overlapping_quantum_args(
214
216
  [op.target, op.value], op.operation.value
215
217
  )
@@ -0,0 +1,16 @@
1
+ from typing import Union
2
+
3
+ from classiq.interface.exceptions import ClassiqError
4
+ from classiq.interface.model.native_function_definition import FunctionSynthesisData
5
+
6
+ from classiq.qmod.quantum_function import ExternalQFunc, GenerativeQFunc, QFunc
7
+
8
+
9
+ def synthesize_separately(qfunc: Union[QFunc, GenerativeQFunc, ExternalQFunc]) -> QFunc:
10
+ if isinstance(qfunc, QFunc):
11
+ qfunc.synthesis_data = FunctionSynthesisData(should_synthesize_separately=True)
12
+ return qfunc
13
+ if isinstance(qfunc, GenerativeQFunc):
14
+ raise ClassiqError("Generative functions can not be synthesized separately")
15
+ if isinstance(qfunc, ExternalQFunc):
16
+ raise ClassiqError("External functions can not be synthesized separately")
@@ -10,7 +10,7 @@ def decl_without_type_attributes(
10
10
  operand_declaration: AnonQuantumOperandDeclaration,
11
11
  ) -> AnonQuantumOperandDeclaration:
12
12
  remover = AttributeRemover()
13
- return operand_declaration.copy(
13
+ return operand_declaration.model_copy(
14
14
  update=dict(
15
15
  positional_arg_declarations=[
16
16
  remover.visit(arg) if isinstance(arg, PortDeclaration) else arg
@@ -31,14 +31,12 @@ def write_qmod(
31
31
  None
32
32
  """
33
33
 
34
- model = Model.parse_raw(serialized_model)
34
+ model = Model.model_validate_json(serialized_model)
35
35
  pretty_printed_model = DSLPrettyPrinter(decimal_precision=decimal_precision).visit(
36
36
  model
37
37
  )
38
38
 
39
- synthesis_options = model.dict(
40
- include={"constraints", "preferences"}, exclude_unset=True
41
- )
39
+ synthesis_options = model.model_dump(include={"constraints", "preferences"})
42
40
 
43
41
  synthesis_options_path = Path(f"{name}.{_SYNTHESIS_OPTIONS_SUFFIX}")
44
42
  if directory is not None:
classiq/synthesis.py CHANGED
@@ -32,8 +32,8 @@ def show(quantum_program: SerializedQuantumProgram) -> None:
32
32
  [Visualization tool](https://docs.classiq.io/latest/reference-manual/analyzer/quantum-program-visualization-tool/)
33
33
  """
34
34
  try:
35
- circuit = QuantumProgram.parse_raw(quantum_program)
36
- except pydantic.error_wrappers.ValidationError as exc:
35
+ circuit = QuantumProgram.model_validate_json(quantum_program)
36
+ except pydantic.ValidationError as exc:
37
37
  raise ClassiqValueError(CANT_PARSE_QUANTUM_PROGRAM_MSG) from exc
38
38
  circuit.show() # type: ignore[attr-defined]
39
39
 
@@ -42,7 +42,7 @@ async def quantum_program_from_qasm_async(qasm: str) -> SerializedQuantumProgram
42
42
  quantum_program = await ApiWrapper.get_generated_circuit_from_qasm(
43
43
  QasmCode(code=qasm)
44
44
  )
45
- return SerializedQuantumProgram(quantum_program.json())
45
+ return SerializedQuantumProgram(quantum_program.model_dump_json())
46
46
 
47
47
 
48
48
  def quantum_program_from_qasm(qasm: str) -> SerializedQuantumProgram:
@@ -61,9 +61,9 @@ def quantum_program_from_qasm(qasm: str) -> SerializedQuantumProgram:
61
61
  async def synthesize_async(
62
62
  serialized_model: SerializedModel,
63
63
  ) -> SerializedQuantumProgram:
64
- model = pydantic.parse_raw_as(Model, serialized_model)
64
+ model = Model.model_validate_json(serialized_model)
65
65
  quantum_program = await ApiWrapper.call_generation_task(model)
66
- return SerializedQuantumProgram(quantum_program.json(indent=2))
66
+ return SerializedQuantumProgram(quantum_program.model_dump_json(indent=2))
67
67
 
68
68
 
69
69
  def synthesize(
@@ -109,7 +109,7 @@ def set_preferences(
109
109
  "Missing preferences. Either pass `Preferences` object or pass keywords"
110
110
  )
111
111
 
112
- model = pydantic.parse_raw_as(Model, serialized_model)
112
+ model = Model.model_validate_json(serialized_model)
113
113
  model.preferences = preferences
114
114
  return model.get_model()
115
115
 
@@ -127,11 +127,10 @@ def update_preferences(
127
127
  Returns:
128
128
  SerializedModel: The updated model with the new preferences applied.
129
129
  """
130
- model = pydantic.parse_raw_as(Model, serialized_model)
130
+ model = Model.model_validate_json(serialized_model)
131
131
 
132
132
  for key, value in kwargs.items():
133
133
  setattr(model.preferences, key, value)
134
-
135
134
  return model.get_model()
136
135
 
137
136
 
@@ -158,7 +157,7 @@ def set_constraints(
158
157
  "Missing constraints. Either pass `Constraints` object or pass keywords"
159
158
  )
160
159
 
161
- model = pydantic.parse_raw_as(Model, serialized_model)
160
+ model = Model.model_validate_json(serialized_model)
162
161
  model.constraints = constraints
163
162
  return model.get_model()
164
163
 
@@ -176,11 +175,10 @@ def update_constraints(
176
175
  Returns:
177
176
  SerializedModel: The updated model with the new constraints applied.
178
177
  """
179
- model = pydantic.parse_raw_as(Model, serialized_model)
178
+ model = Model.model_validate_json(serialized_model)
180
179
 
181
180
  for key, value in kwargs.items():
182
181
  setattr(model.constraints, key, value)
183
-
184
182
  return model.get_model()
185
183
 
186
184
 
@@ -208,7 +206,7 @@ def set_execution_preferences(
208
206
  "Missing execution_preferences. Either pass `ExecutionPreferences` object or pass keywords"
209
207
  )
210
208
 
211
- model = pydantic.parse_raw_as(Model, serialized_model)
209
+ model = Model.model_validate_json(serialized_model)
212
210
  model.execution_preferences = execution_preferences
213
211
  return model.get_model()
214
212
 
@@ -226,7 +224,7 @@ def update_execution_preferences(
226
224
  Returns:
227
225
  SerializedModel: The updated model with the new execution_preferences applied.
228
226
  """
229
- model = pydantic.parse_raw_as(Model, serialized_model)
227
+ model = Model.model_validate_json(serialized_model)
230
228
 
231
229
  for key, value in kwargs.items():
232
230
  setattr(model.execution_preferences, key, value)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: classiq
3
- Version: 0.51.1
3
+ Version: 0.53.0
4
4
  Summary: Classiq's Python SDK for quantum computing
5
5
  Home-page: https://classiq.io
6
6
  License: Proprietary
@@ -46,7 +46,8 @@ Requires-Dist: numpy (>=1.26.0,<2.0.0) ; python_version >= "3.12"
46
46
  Requires-Dist: packaging (>=23.2,<24.0)
47
47
  Requires-Dist: pandas (>=1.4.0,<3.0.0)
48
48
  Requires-Dist: plotly (>=5.7.0,<6.0.0)
49
- Requires-Dist: pydantic (>=1.9.1,<2.0.0)
49
+ Requires-Dist: pydantic (>=2.9.0,<3.0.0)
50
+ Requires-Dist: pydantic-settings (>=2.4.0,<3.0.0)
50
51
  Requires-Dist: scipy (>=1.10.0,<2.0.0) ; python_version < "3.12"
51
52
  Requires-Dist: scipy (>=1.11.0,<2.0.0) ; python_version >= "3.12"
52
53
  Requires-Dist: sympy (>=1.13.0,<2.0.0)