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
@@ -1,6 +1,8 @@
1
- from typing import Any, Dict, List, Optional, Tuple, Union
1
+ from typing import Any, Dict, List, Literal, Optional, Tuple, Union
2
2
 
3
3
  import pydantic
4
+ from pydantic import Field
5
+ from typing_extensions import Annotated
4
6
 
5
7
  from classiq.interface.chemistry.fermionic_operator import SummedFermionicOperator
6
8
  from classiq.interface.chemistry.molecule import Molecule
@@ -9,6 +11,7 @@ from classiq.interface.helpers.hashable_pydantic_base_model import (
9
11
  )
10
12
 
11
13
  from classiq._internals.enum_utils import StrEnum
14
+ from classiq.exceptions import ClassiqValueError
12
15
 
13
16
  """
14
17
  The correct type hint is:
@@ -37,6 +40,8 @@ class FermionMapping(StrEnum):
37
40
 
38
41
 
39
42
  class GroundStateProblem(HashablePydanticBaseModel):
43
+ kind: str
44
+
40
45
  mapping: FermionMapping = pydantic.Field(
41
46
  default=FermionMapping.JORDAN_WIGNER,
42
47
  description="Fermionic mapping type",
@@ -53,7 +58,7 @@ class GroundStateProblem(HashablePydanticBaseModel):
53
58
  cls, z2_symmetries: bool, values: Dict[str, Any]
54
59
  ) -> bool:
55
60
  if z2_symmetries and values.get("mapping") == FermionMapping.FAST_BRAVYI_KITAEV:
56
- raise ValueError(
61
+ raise ClassiqValueError(
57
62
  "z2 symmetries reduction can not be used for fast_bravyi_kitaev mapping"
58
63
  )
59
64
  return z2_symmetries
@@ -63,6 +68,8 @@ class GroundStateProblem(HashablePydanticBaseModel):
63
68
 
64
69
 
65
70
  class MoleculeProblem(GroundStateProblem):
71
+ kind: Literal["molecule"] = pydantic.Field(default="molecule")
72
+
66
73
  molecule: Molecule
67
74
  basis: str = pydantic.Field(default="sto3g", description="Molecular basis set")
68
75
  freeze_core: bool = pydantic.Field(default=False)
@@ -72,6 +79,8 @@ class MoleculeProblem(GroundStateProblem):
72
79
 
73
80
 
74
81
  class HamiltonianProblem(GroundStateProblem):
82
+ kind: Literal["hamiltonian"] = pydantic.Field(default="hamiltonian")
83
+
75
84
  hamiltonian: SummedFermionicOperator = pydantic.Field(
76
85
  description="Hamiltonian as a fermionic operator"
77
86
  )
@@ -96,5 +105,11 @@ class HamiltonianProblem(GroundStateProblem):
96
105
 
97
106
 
98
107
  CHEMISTRY_PROBLEMS = (MoleculeProblem, HamiltonianProblem)
99
- CHEMISTRY_PROBLEMS_TYPE = Union[MoleculeProblem, HamiltonianProblem]
108
+ CHEMISTRY_PROBLEMS_TYPE = Annotated[
109
+ Union[MoleculeProblem, HamiltonianProblem],
110
+ Field(
111
+ discriminator="kind",
112
+ description="Ground state problem object describing the system.",
113
+ ),
114
+ ]
100
115
  CHEMISTRY_ANSATZ_NAMES = ["hw_efficient", "ucc", "hva"]
@@ -8,6 +8,8 @@ from classiq.interface.helpers.hashable_pydantic_base_model import (
8
8
  HashablePydanticBaseModel,
9
9
  )
10
10
 
11
+ from classiq.exceptions import ClassiqValueError
12
+
11
13
 
12
14
  class Atom(HashablePydanticBaseModel):
13
15
  symbol: Literal[tuple(ELEMENTS)] = pydantic.Field(description="The atom symbol") # type: ignore[valid-type]
@@ -41,20 +43,20 @@ class Molecule(HashablePydanticBaseModel):
41
43
  @staticmethod
42
44
  def _validate_old_atoms_type(atom: AtomType) -> Atom:
43
45
  if len(atom) != 2:
44
- raise ValueError(
46
+ raise ClassiqValueError(
45
47
  "each atom should be a list of two entries: 1) name pf the elemnt (str) 2) list of its (x,y,z) location"
46
48
  )
47
- if type(atom[0]) is not str:
48
- raise ValueError(
49
+ if not isinstance(atom[0], str):
50
+ raise ClassiqValueError(
49
51
  f"atom name should be a string. unknown element: {atom[0]}."
50
52
  )
51
53
  if len(atom[1]) != 3:
52
- raise ValueError(
54
+ raise ClassiqValueError(
53
55
  f"location of the atom is of length three, representing the (x,y,z) coordinates of the atom, error value: {atom[1]}"
54
56
  )
55
57
  for idx in atom[1]:
56
- if type(idx) is not float and type(idx) is not int:
57
- raise ValueError(
58
+ if not isinstance(idx, (float, int)):
59
+ raise ClassiqValueError(
58
60
  f"coordinates of the atom should be of type float. error value: {idx}"
59
61
  )
60
62
  symbol, coordinate = atom
@@ -71,7 +71,7 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
71
71
  @pydantic.validator("pauli_list")
72
72
  def _validate_pauli_list(cls, pauli_list: PydanticPauliList) -> PydanticPauliList:
73
73
  if not all_equal(len(summand[0]) for summand in pauli_list):
74
- raise ValueError("Pauli strings have incompatible lengths.")
74
+ raise ClassiqValueError("Pauli strings have incompatible lengths.")
75
75
  return pauli_list
76
76
 
77
77
  @pydantic.root_validator
@@ -172,16 +172,18 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
172
172
  num_extra_qubits: int,
173
173
  ) -> None:
174
174
  if num_extra_qubits < 0:
175
- raise ValueError("Number of extra qubits cannot be negative")
175
+ raise ClassiqValueError("Number of extra qubits cannot be negative")
176
176
 
177
177
  if len(order) != num_qubits:
178
- raise ValueError("The qubits order doesn't match the Pauli operator")
178
+ raise ClassiqValueError("The qubits order doesn't match the Pauli operator")
179
179
 
180
180
  if len(order) != len(set(order)):
181
- raise ValueError("The qubits order is not one-to-one")
181
+ raise ClassiqValueError("The qubits order is not one-to-one")
182
182
 
183
183
  if not all(pos < num_qubits + num_extra_qubits for pos in order):
184
- raise ValueError("The qubits order contains qubits which do no exist")
184
+ raise ClassiqValueError(
185
+ "The qubits order contains qubits which do no exist"
186
+ )
185
187
 
186
188
  @classmethod
187
189
  def reorder(
@@ -209,7 +211,7 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
209
211
  coefficients = [1] * len(operators)
210
212
 
211
213
  if len(operators) != len(coefficients):
212
- raise ValueError(
214
+ raise ClassiqValueError(
213
215
  f"The number of coefficients ({len(coefficients)}) must be equal to the number of pauli operators ({len(operators)})"
214
216
  )
215
217
 
@@ -269,7 +271,7 @@ class PauliOperatorV1(HashablePydanticBaseModel):
269
271
  @pydantic.validator("pauli_list")
270
272
  def _validate_pauli_list(cls, pauli_list: PydanticPauliList) -> PydanticPauliList:
271
273
  if not all_equal(len(summand[0]) for summand in pauli_list):
272
- raise ValueError("Pauli strings have incompatible lengths.")
274
+ raise ClassiqValueError("Pauli strings have incompatible lengths.")
273
275
  return pauli_list
274
276
 
275
277
  @pydantic.root_validator
@@ -370,16 +372,18 @@ class PauliOperatorV1(HashablePydanticBaseModel):
370
372
  num_extra_qubits: int,
371
373
  ) -> None:
372
374
  if num_extra_qubits < 0:
373
- raise ValueError("Number of extra qubits cannot be negative")
375
+ raise ClassiqValueError("Number of extra qubits cannot be negative")
374
376
 
375
377
  if len(order) != num_qubits:
376
- raise ValueError("The qubits order doesn't match the Pauli operator")
378
+ raise ClassiqValueError("The qubits order doesn't match the Pauli operator")
377
379
 
378
380
  if len(order) != len(set(order)):
379
- raise ValueError("The qubits order is not one-to-one")
381
+ raise ClassiqValueError("The qubits order is not one-to-one")
380
382
 
381
383
  if not all(pos < num_qubits + num_extra_qubits for pos in order):
382
- raise ValueError("The qubits order contains qubits which do no exist")
384
+ raise ClassiqValueError(
385
+ "The qubits order contains qubits which do no exist"
386
+ )
383
387
 
384
388
  @classmethod
385
389
  def reorder(
@@ -407,7 +411,7 @@ class PauliOperatorV1(HashablePydanticBaseModel):
407
411
  coefficients = [1] * len(operators)
408
412
 
409
413
  if len(operators) != len(coefficients):
410
- raise ValueError(
414
+ raise ClassiqValueError(
411
415
  f"The number of coefficients ({len(coefficients)}) must be equal to the number of pauli operators ({len(operators)})"
412
416
  )
413
417
 
@@ -448,7 +452,7 @@ def to_pauli_matrix(pauli_op: PydanticPauliMonomialStr) -> np.ndarray:
448
452
 
449
453
  def validate_operator_is_hermitian(pauli_operator: PauliOperator) -> PauliOperator:
450
454
  if not pauli_operator.is_hermitian:
451
- raise ValueError("Coefficients of the Hamiltonian must be real numbers")
455
+ raise ClassiqValueError("Coefficients of the Hamiltonian must be real numbers")
452
456
  return pauli_operator
453
457
 
454
458
 
@@ -456,7 +460,9 @@ def validate_operator_has_no_complex_coefficients(
456
460
  pauli_operator: PauliOperator,
457
461
  ) -> PauliOperator:
458
462
  if pauli_operator.has_complex_coefficients:
459
- raise ValueError("Coefficients of the Hamiltonian mustn't be complex numbers")
463
+ raise ClassiqValueError(
464
+ "Coefficients of the Hamiltonian mustn't be complex numbers"
465
+ )
460
466
  return pauli_operator
461
467
 
462
468
 
@@ -11,7 +11,7 @@ def ascending_sequence(coeffs: List[int], bound: int) -> pyo.ConcreteModel:
11
11
  )
12
12
 
13
13
  @model.Constraint(range(len(coeffs) - 1))
14
- def monotone_rule(model, idx):
14
+ def monotone_rule(model: pyo.ConcreteModel, idx: int) -> pyo.ExpressionBase:
15
15
  return model.x[idx] <= model.x[idx + 1]
16
16
 
17
17
  model.cost = pyo.Objective(
@@ -19,7 +19,7 @@ def greater_than_ilp(
19
19
  )
20
20
 
21
21
  @model.Constraint(range(num_constraints))
22
- def monotone_rule(model, idx):
22
+ def monotone_rule(model: pyo.ConcreteModel, idx: int) -> pyo.ExpressionBase:
23
23
  return a[idx, :] @ list(model.x.values()) >= float(b[idx])
24
24
 
25
25
  # model objective: max(c * x)
@@ -1,5 +1,6 @@
1
1
  import numpy as np
2
2
  import pyomo.core as pyo
3
+ import pyomo.core.expr.numeric_expr as pyo_expr
3
4
 
4
5
 
5
6
  def ilp(a: np.ndarray, b: np.ndarray, c: np.ndarray, bound: int) -> pyo.ConcreteModel:
@@ -17,7 +18,7 @@ def ilp(a: np.ndarray, b: np.ndarray, c: np.ndarray, bound: int) -> pyo.Concrete
17
18
  )
18
19
 
19
20
  @model.Constraint(range(num_constraints))
20
- def monotone_rule(model, idx):
21
+ def monotone_rule(model: pyo.ConcreteModel, idx: int) -> pyo_expr.ExpressionBase:
21
22
  return a[idx, :] @ list(model.x.values()) <= float(b[idx])
22
23
 
23
24
  # model objective: max(c * x)
@@ -1,4 +1,4 @@
1
- from typing import List
1
+ from typing import List, Tuple
2
2
 
3
3
  import numpy as np
4
4
  import pyomo.core as pyo
@@ -10,7 +10,7 @@ def integer_portfolio_optimization(
10
10
  model = pyo.ConcreteModel()
11
11
  num_assets = len(returns)
12
12
 
13
- def bounds(_, i):
13
+ def bounds(model: pyo.ConcreteModel, i: int) -> Tuple[int, int]:
14
14
  return 0, upper_bounds[i]
15
15
 
16
16
  model.x = pyo.Var(range(num_assets), domain=pyo.NonNegativeIntegers, bounds=bounds)
@@ -1,5 +1,6 @@
1
1
  import networkx as nx
2
2
  import pyomo.core as pyo
3
+ import pyomo.core.expr.numeric_expr as pyo_expr
3
4
 
4
5
 
5
6
  def mds(graph: nx.Graph) -> pyo.ConcreteModel:
@@ -7,7 +8,7 @@ def mds(graph: nx.Graph) -> pyo.ConcreteModel:
7
8
  model.x = pyo.Var(graph.nodes, domain=pyo.Binary)
8
9
 
9
10
  @model.Constraint(graph.nodes)
10
- def dominating_rule(model, idx):
11
+ def dominating_rule(model: pyo.ConcreteModel, idx: int) -> pyo_expr.ExpressionBase:
11
12
  sum_of_neighbors = sum(model.x[neighbor] for neighbor in graph.neighbors(idx))
12
13
  return model.x[idx] + sum_of_neighbors >= 1
13
14
 
@@ -22,7 +22,7 @@ def build_mht_pyomo_model(
22
22
  if has_constraints:
23
23
 
24
24
  @model.Constraint(model.Nodes)
25
- def out_edges_rule(model, idx):
25
+ def out_edges_rule(model: pyo.ConcreteModel, idx: int) -> pyo.ExpressionBase:
26
26
  out_nodes = [
27
27
  node_id for node_id in model.Nodes if [idx, node_id] in model.Arcs
28
28
  ]
@@ -32,7 +32,7 @@ def build_mht_pyomo_model(
32
32
  return pyo.Constraint.Feasible
33
33
 
34
34
  @model.Constraint(model.Nodes)
35
- def in_edges_rule(model, idx):
35
+ def in_edges_rule(model: pyo.ConcreteModel, idx: int) -> pyo.ExpressionBase:
36
36
  in_nodes = [
37
37
  node_id for node_id in model.Nodes if [node_id, idx] in model.Arcs
38
38
  ]
@@ -41,7 +41,7 @@ def build_mht_pyomo_model(
41
41
  else:
42
42
  return pyo.Constraint.Feasible
43
43
 
44
- def obj_expression(model):
44
+ def obj_expression(model: pyo.ConcreteModel) -> pyo.ExpressionBase:
45
45
  return sum(
46
46
  round(pubo_energy, _decimals)
47
47
  * math.prod(model.x[edge] for edge in pubo_edges)
@@ -1,5 +1,6 @@
1
1
  import networkx as nx
2
2
  import pyomo.core as pyo
3
+ import pyomo.core.expr.numeric_expr as pyo_expr
3
4
 
4
5
 
5
6
  def mis(graph: nx.Graph) -> pyo.ConcreteModel:
@@ -7,7 +8,9 @@ def mis(graph: nx.Graph) -> pyo.ConcreteModel:
7
8
  model.x = pyo.Var(graph.nodes, domain=pyo.Binary)
8
9
 
9
10
  @model.Constraint(graph.edges)
10
- def independent_rule(model, node1, node2):
11
+ def independent_rule(
12
+ model: pyo.ConcreteModel, node1: int, node2: int
13
+ ) -> pyo_expr.ExpressionBase:
11
14
  return model.x[node1] + model.x[node2] <= 1
12
15
 
13
16
  model.cost = pyo.Objective(expr=sum(model.x.values()), sense=pyo.maximize)
@@ -1,5 +1,6 @@
1
1
  import networkx as nx
2
2
  import pyomo.core as pyo
3
+ import pyomo.core.expr.numeric_expr as pyo_expr
3
4
 
4
5
 
5
6
  def mvc(graph: nx.Graph, k: int) -> pyo.ConcreteModel:
@@ -7,7 +8,7 @@ def mvc(graph: nx.Graph, k: int) -> pyo.ConcreteModel:
7
8
  model.x = pyo.Var(graph.nodes, domain=pyo.Binary)
8
9
  model.amount_constraint = pyo.Constraint(expr=sum(model.x.values()) == k)
9
10
 
10
- def obj_expression(model):
11
+ def obj_expression(model: pyo.ConcreteModel) -> pyo_expr.ExpressionBase:
11
12
  # number of edges not covered
12
13
  return sum((1 - model.x[i]) * (1 - model.x[j]) for i, j in graph.edges)
13
14
 
@@ -2,6 +2,7 @@ import itertools
2
2
  from typing import List
3
3
 
4
4
  import pyomo.core as pyo
5
+ import pyomo.core.expr.numeric_expr as pyo_expr
5
6
 
6
7
 
7
8
  def set_cover(sub_sets: List[List[int]]) -> pyo.ConcreteModel:
@@ -16,7 +17,7 @@ def set_cover(sub_sets: List[List[int]]) -> pyo.ConcreteModel:
16
17
  model.x = pyo.Var(range(num_sets), domain=pyo.Binary)
17
18
 
18
19
  @model.Constraint(entire_set)
19
- def independent_rule(model, num):
20
+ def independent_rule(model: pyo.ConcreteModel, num: int) -> pyo_expr.ExpressionBase:
20
21
  return sum(model.x[idx] for idx in range(num_sets) if num in sub_sets[idx]) >= 1
21
22
 
22
23
  model.cost = pyo.Objective(expr=sum(model.x.values()), sense=pyo.minimize)
@@ -2,6 +2,7 @@ import itertools
2
2
 
3
3
  import numpy as np
4
4
  import pyomo.core as pyo
5
+ import pyomo.core.expr.numeric_expr as pyo_expr
5
6
 
6
7
 
7
8
  def tsp(distance_matrix: np.ndarray) -> pyo.ConcreteModel:
@@ -22,16 +23,16 @@ def tsp(distance_matrix: np.ndarray) -> pyo.ConcreteModel:
22
23
  @model.Constraint(points)
23
24
  def each_step_visits_one_point_rule(
24
25
  model: pyo.ConcreteModel, ii: int
25
- ) -> pyo.ExpressionBase:
26
+ ) -> pyo_expr.ExpressionBase:
26
27
  return sum(model.x[ii, jj] for jj in range(num_points)) == 1
27
28
 
28
29
  @model.Constraint(points)
29
30
  def each_point_visited_once_rule(
30
31
  model: pyo.ConcreteModel, jj: int
31
- ) -> pyo.ExpressionBase:
32
+ ) -> pyo_expr.ExpressionBase:
32
33
  return sum(model.x[ii, jj] for ii in range(num_points)) == 1
33
34
 
34
- def is_travel_between_2_points(point1: int, point2: int) -> pyo.ExpressionBase:
35
+ def is_travel_between_2_points(point1: int, point2: int) -> pyo_expr.ExpressionBase:
35
36
  return sum(model.x[point1, kk] * model.x[point2, kk + 1] for kk in points[:-1])
36
37
 
37
38
  model.cost = pyo.Objective(
@@ -21,11 +21,15 @@ def tsp_digraph(
21
21
  ) # x[i, j] = 1 indicates that point i is visited at step j
22
22
 
23
23
  @model.Constraint(points)
24
- def each_step_visits_one_point_rule(model, ii):
24
+ def each_step_visits_one_point_rule(
25
+ model: pyo.ConcreteModel, ii: int
26
+ ) -> pyo.ExpressionBase:
25
27
  return sum(model.x[ii, jj] for jj in steps) == 1
26
28
 
27
29
  @model.Constraint(steps)
28
- def each_point_visited_once_rule(model, jj):
30
+ def each_point_visited_once_rule(
31
+ model: pyo.ConcreteModel, jj: int
32
+ ) -> pyo.ExpressionBase:
29
33
  return sum(model.x[ii, jj] for ii in points) == 1
30
34
 
31
35
  def is_travel_between_2_points(point1: int, point2: int) -> pyo.ExpressionBase:
@@ -5,6 +5,8 @@ import numpy as np
5
5
  import pydantic
6
6
  from pydantic import BaseModel
7
7
 
8
+ from classiq.exceptions import ClassiqValueError
9
+
8
10
  _TOLERANCE_DECIMALS = 6
9
11
 
10
12
 
@@ -52,7 +54,9 @@ class MhtQaoaInput(BaseModel):
52
54
  return True
53
55
 
54
56
  @pydantic.validator("plot_list")
55
- def round_plot_list_times_and_validate(cls, plot_list):
57
+ def round_plot_list_times_and_validate(
58
+ cls, plot_list: List[PlotData]
59
+ ) -> List[PlotData]:
56
60
  MhtQaoaInput._check_all_ids_are_distinct(plot_list)
57
61
  MhtQaoaInput._round_to_tolerance_decimals(plot_list)
58
62
 
@@ -63,7 +67,9 @@ class MhtQaoaInput(BaseModel):
63
67
  }
64
68
 
65
69
  if len(time_diff_set) != 1:
66
- raise ValueError("The time difference between each time stamp is not equal")
70
+ raise ClassiqValueError(
71
+ "The time difference between each time stamp is not equal"
72
+ )
67
73
 
68
74
  return plot_list
69
75
 
@@ -75,4 +81,4 @@ class MhtQaoaInput(BaseModel):
75
81
  @staticmethod
76
82
  def _check_all_ids_are_distinct(plot_list: List[PlotData]) -> None:
77
83
  if not more_itertools.all_unique(plot.plot_id for plot in plot_list):
78
- raise ValueError("Plot IDs should be unique.")
84
+ raise ClassiqValueError("Plot IDs should be unique.")
@@ -1,10 +1,11 @@
1
1
  from datetime import date
2
- from typing import List, Optional
2
+ from typing import Any, Dict, List, Optional
3
3
 
4
4
  import pydantic
5
5
  from pydantic import validator
6
6
 
7
7
  from classiq._internals.enum_utils import StrEnum
8
+ from classiq.exceptions import ClassiqValueError
8
9
 
9
10
 
10
11
  class Granularity(StrEnum):
@@ -37,9 +38,9 @@ class ExecutionCostForTimePeriod(pydantic.BaseModel):
37
38
  json_encoders = {date: lambda v: v.strftime("%Y-%m-%d")}
38
39
 
39
40
  @validator("end")
40
- def date_order(cls, v, values, **kwargs):
41
+ def date_order(cls, v: date, values: Dict[str, Any], **kwargs: Any) -> date:
41
42
  if "start" in values and v <= values["start"]:
42
- raise ValueError('"end" date should be after "start" date')
43
+ raise ClassiqValueError('"end" date should be after "start" date')
43
44
  return v
44
45
 
45
46
 
@@ -1,7 +1,7 @@
1
1
  import pydantic
2
2
 
3
3
  from classiq.interface.chemistry.operator import PauliOperators
4
- from classiq.interface.executor.quantum_program import QuantumProgram
4
+ from classiq.interface.executor.quantum_code import QuantumCode
5
5
 
6
6
 
7
7
  class OperatorsEstimation(pydantic.BaseModel):
@@ -10,5 +10,5 @@ class OperatorsEstimation(pydantic.BaseModel):
10
10
  by a quantum program.
11
11
  """
12
12
 
13
- quantum_program: QuantumProgram
13
+ quantum_program: QuantumCode
14
14
  operators: PauliOperators
@@ -1,5 +1,5 @@
1
1
  from datetime import timedelta
2
- from typing import Any, Dict, List, Optional, TypeVar, Union
2
+ from typing import Any, Dict, Optional, TypeVar
3
3
 
4
4
  import pydantic
5
5
 
@@ -23,6 +23,7 @@ from classiq.interface.generator.model.preferences.randomness import create_rand
23
23
  from classiq.interface.generator.noise_properties import NoiseProperties
24
24
 
25
25
  from classiq._internals.enum_utils import ReprEnum
26
+ from classiq.exceptions import ClassiqValueError
26
27
 
27
28
  DIFFERENT_TIMEOUT_MSG = (
28
29
  "Timeout is defined differently in the execution preferences and the "
@@ -40,41 +41,12 @@ class QaeWithQpeEstimationMethod(int, ReprEnum):
40
41
  BEST_FIT = 1
41
42
 
42
43
 
43
- class AmplitudeAmplification(pydantic.BaseModel):
44
- iterations: List[int] = pydantic.Field(
45
- default_factory=list,
46
- description="Number or list of numbers of iteration to use",
47
- )
48
- growth_rate: float = pydantic.Field(
49
- default=1.25,
50
- description="Number of iteration used is set to round(growth_rate**iterations)",
51
- )
52
- sample_from_iterations: bool = pydantic.Field(
53
- default=False,
54
- description="If True, number of iterations used is picked randomly from "
55
- "[1, iteration] range",
56
- )
57
- num_of_highest_probability_states_to_check: pydantic.PositiveInt = pydantic.Field(
58
- default=1, description="Then number of highest probability states to check"
59
- )
60
-
61
- @pydantic.validator("iterations")
62
- def _validate_iterations(cls, iterations: Union[List[int], int]) -> List[int]:
63
- if isinstance(iterations, int):
64
- return [iterations]
65
- return iterations
66
-
67
-
68
44
  class ExecutionPreferences(pydantic.BaseModel):
69
45
  timeout_sec: Optional[pydantic.PositiveInt] = pydantic.Field(
70
46
  default=None,
71
47
  description="If set, limits the execution runtime. Value is in seconds. "
72
48
  "Not supported on all platforms.",
73
49
  )
74
- amplitude_amplification: AmplitudeAmplification = pydantic.Field(
75
- default_factory=AmplitudeAmplification,
76
- description="Settings related to amplitude amplification execution, used during the grover execution.",
77
- )
78
50
  optimizer_preferences: Optional[OptimizerPreferences] = pydantic.Field(
79
51
  default_factory=None,
80
52
  description="Settings related to VQE execution.",
@@ -130,9 +102,9 @@ class ExecutionPreferences(pydantic.BaseModel):
130
102
  timeout != backend_preferences.job_timeout
131
103
  and backend_preferences.job_timeout != AWS_DEFAULT_JOB_TIMEOUT_SECONDS
132
104
  ):
133
- raise ValueError(DIFFERENT_TIMEOUT_MSG)
105
+ raise ClassiqValueError(DIFFERENT_TIMEOUT_MSG)
134
106
  if timeout > MAX_EXECUTION_TIMEOUT_SECONDS:
135
- raise ValueError(TIMEOUT_LARGE_FOR_AWS_MSG)
107
+ raise ClassiqValueError(TIMEOUT_LARGE_FOR_AWS_MSG)
136
108
 
137
109
  backend_preferences.job_timeout = timeout
138
110
  return backend_preferences
@@ -169,7 +141,7 @@ def _choose_original_or_optimizer_attribute(
169
141
  return optimizer_attribute
170
142
 
171
143
  elif original_attribute != optimizer_attribute:
172
- raise ValueError(
144
+ raise ClassiqValueError(
173
145
  f"Different {attribure_name} were given for ExecutionPreferences and OptimizerPreferences."
174
146
  )
175
147
 
@@ -179,7 +151,6 @@ def _choose_original_or_optimizer_attribute(
179
151
 
180
152
  __all__ = [
181
153
  "ExecutionPreferences",
182
- "AmplitudeAmplification",
183
154
  "ErrorMitigationMethod",
184
155
  "NoiseProperties",
185
156
  "OptimizerPreferences",
@@ -2,38 +2,40 @@ from datetime import datetime
2
2
  from typing import Any, Dict, List, Literal, Optional, Union
3
3
 
4
4
  import pydantic
5
- from pydantic import BaseModel
5
+ from pydantic import BaseModel, Field
6
+ from typing_extensions import Annotated
6
7
 
7
8
  from classiq.interface.backend.backend_preferences import IonqBackendPreferences
8
9
  from classiq.interface.executor.estimation import OperatorsEstimation
9
10
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
10
- from classiq.interface.executor.quantum_program import (
11
- QuantumInstructionSet,
12
- QuantumProgram,
13
- )
14
- from classiq.interface.generator.generated_circuit import GeneratedCircuit
11
+ from classiq.interface.executor.quantum_code import QuantumCode, QuantumInstructionSet
12
+ from classiq.interface.generator.quantum_program import QuantumProgram
13
+ from classiq.interface.helpers.custom_encoders import CUSTOM_ENCODERS
15
14
  from classiq.interface.helpers.versioned_model import VersionedModel
16
15
  from classiq.interface.jobs import JobStatus
17
16
 
18
-
19
- class GeneratedCircuitExecution(GeneratedCircuit):
20
- execution_type: Literal["generated_circuit"] = "generated_circuit"
17
+ from classiq.exceptions import ClassiqValueError
21
18
 
22
19
 
23
20
  class QuantumProgramExecution(QuantumProgram):
24
- execution_type: Literal["quantum_program"] = "quantum_program"
21
+ execution_type: Literal["quantum_program2"] = "quantum_program2"
22
+
23
+
24
+ class QuantumCodeExecution(QuantumCode):
25
+ execution_type: Literal["quantum_code"] = "quantum_code"
25
26
 
26
27
 
27
28
  class EstimateOperatorsExecution(OperatorsEstimation):
28
29
  execution_type: Literal["estimate_operators"] = "estimate_operators"
29
30
 
30
31
 
31
- ExecutionPayloads = Union[
32
- GeneratedCircuitExecution, QuantumProgramExecution, EstimateOperatorsExecution
32
+ ExecutionPayloads = Annotated[
33
+ Union[QuantumProgramExecution, QuantumCodeExecution, EstimateOperatorsExecution],
34
+ Field(discriminator="execution_type"),
33
35
  ]
34
36
 
35
37
 
36
- class ExecutionRequest(BaseModel):
38
+ class ExecutionRequest(BaseModel, json_encoders=CUSTOM_ENCODERS):
37
39
  execution_payload: ExecutionPayloads
38
40
  preferences: ExecutionPreferences = pydantic.Field(
39
41
  default_factory=ExecutionPreferences,
@@ -58,23 +60,23 @@ class ExecutionRequest(BaseModel):
58
60
  is_ionq_backend = isinstance(
59
61
  preferences.backend_preferences, IonqBackendPreferences
60
62
  )
61
- if isinstance(quantum_program, QuantumProgram):
63
+ if isinstance(quantum_program, QuantumCode):
62
64
  if (
63
65
  quantum_program.syntax == QuantumInstructionSet.IONQ
64
66
  and not is_ionq_backend
65
67
  ):
66
- raise ValueError("Can only execute IonQ code on IonQ backend.")
68
+ raise ClassiqValueError("Can only execute IonQ code on IonQ backend.")
67
69
  else:
68
70
  # If we handle anything other than a program.
69
71
  if is_ionq_backend:
70
- raise ValueError(
72
+ raise ClassiqValueError(
71
73
  "IonQ backend supports only execution of QuantumPrograms"
72
74
  )
73
75
  return preferences
74
76
 
75
77
 
76
78
  class QuantumProgramExecutionRequest(ExecutionRequest):
77
- execution_payload: QuantumProgramExecution
79
+ execution_payload: QuantumCodeExecution
78
80
 
79
81
 
80
82
  class ExecutionJobDetails(VersionedModel):