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
@@ -6,6 +6,8 @@ from classiq.interface.generator.arith.register_user_input import RegisterUserIn
6
6
  from classiq.interface.generator.control_state import ControlState
7
7
  from classiq.interface.generator.function_params import FunctionParams
8
8
 
9
+ from classiq.exceptions import ClassiqValueError
10
+
9
11
  CTRL = "CTRL_IN"
10
12
  TARGET_QUBIT = "TARGET_QUBIT"
11
13
 
@@ -29,9 +31,9 @@ class Mcx(FunctionParams):
29
31
  ) -> List[RegisterUserInput]:
30
32
  register_name_list: List[Optional[str]] = [arg.name for arg in arguments]
31
33
  if None in register_name_list:
32
- raise ValueError("All registers must be named")
34
+ raise ClassiqValueError("All registers must be named")
33
35
  if len(set(register_name_list)) != len(register_name_list):
34
- raise ValueError("Registers must have distinct names")
36
+ raise ClassiqValueError("Registers must have distinct names")
35
37
  return arguments
36
38
 
37
39
  @pydantic.validator("num_ctrl_qubits", always=True)
@@ -42,14 +44,14 @@ class Mcx(FunctionParams):
42
44
  num_ctrl_qubits = arguments_size - 1
43
45
 
44
46
  if num_ctrl_qubits < 1:
45
- raise ValueError("Must have control qubits")
47
+ raise ClassiqValueError("Must have control qubits")
46
48
 
47
49
  if arguments_size == 0:
48
50
  ctrl_register = RegisterUserInput(size=num_ctrl_qubits, name=CTRL)
49
51
  target_register = RegisterUserInput(size=1, name=TARGET_QUBIT)
50
52
  values["arguments"] = [ctrl_register, target_register]
51
53
  elif num_ctrl_qubits != arguments_size - 1:
52
- raise ValueError("Given sizes do not match")
54
+ raise ClassiqValueError("Given sizes do not match")
53
55
  return num_ctrl_qubits
54
56
 
55
57
  @pydantic.validator("ctrl_state", always=True)
@@ -58,7 +60,7 @@ class Mcx(FunctionParams):
58
60
  if not ctrl_state:
59
61
  return "1" * num_ctrl_qubits
60
62
  if len(ctrl_state) != num_ctrl_qubits:
61
- raise ValueError(
63
+ raise ClassiqValueError(
62
64
  "control state length should be equal to the number of control qubits"
63
65
  )
64
66
  ControlState.validate_control_string(ctrl_state)
@@ -7,6 +7,7 @@ from pydantic import BaseModel, Extra
7
7
  from classiq.interface.generator.transpiler_basis_gates import TranspilerBasisGates
8
8
 
9
9
  from classiq._internals.enum_utils import StrEnum
10
+ from classiq.exceptions import ClassiqValueError
10
11
 
11
12
  UNCONSTRAINED = -1
12
13
 
@@ -26,7 +27,7 @@ def optimization_parameter_type_from_string(param: str) -> OptimizationParameter
26
27
  return enum_(param) # type: ignore[return-value]
27
28
  except ValueError:
28
29
  pass
29
- raise ValueError(f"Invalid OptimizationParameterType {param}")
30
+ raise ClassiqValueError(f"Invalid OptimizationParameterType {param}")
30
31
 
31
32
 
32
33
  class Constraints(BaseModel, extra=Extra.forbid):
@@ -5,7 +5,7 @@ import pydantic
5
5
 
6
6
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
7
7
  from classiq.interface.generator.constant import Constant
8
- from classiq.interface.generator.function_params import IOName
8
+ from classiq.interface.generator.function_params import ArithmeticIODict, IOName
9
9
  from classiq.interface.generator.functions import (
10
10
  SynthesisNativeFunctionDefinition,
11
11
  SynthesisPortDeclaration,
@@ -22,14 +22,8 @@ from classiq.interface.generator.quantum_function_call import (
22
22
  WireDict,
23
23
  WireName,
24
24
  )
25
- from classiq.interface.generator.types.combinatorial_problem import (
26
- CombinatorialOptimizationStructDeclaration,
27
- )
28
25
  from classiq.interface.generator.types.struct_declaration import StructDeclaration
29
- from classiq.interface.helpers.pydantic_model_helpers import (
30
- get_discriminator_field,
31
- nameables_to_dict,
32
- )
26
+ from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
33
27
  from classiq.interface.helpers.validation_helpers import is_list_unique
34
28
  from classiq.interface.helpers.versioned_model import VersionedModel
35
29
 
@@ -45,10 +39,6 @@ DEFAULT_PORT_SIZE = 1
45
39
 
46
40
  SerializedModel = NewType("SerializedModel", str)
47
41
 
48
- ConcreteStructDeclaration = Union[
49
- CombinatorialOptimizationStructDeclaration, StructDeclaration
50
- ]
51
-
52
42
  # We need to define ConcreteFunctionData so pydantic will know
53
43
  # what class to use when deserializing from object (pydantic attempts to
54
44
  # parse as each of the classes in the Union, in order).
@@ -70,7 +60,7 @@ class ClassiqBaseModel(VersionedModel, ABC):
70
60
  All the relevant data for evaluating execution in one place.
71
61
  """
72
62
 
73
- types: List[ConcreteStructDeclaration] = pydantic.Field(
63
+ types: List[StructDeclaration] = pydantic.Field(
74
64
  default_factory=list,
75
65
  description="The user-defined custom function library.",
76
66
  )
@@ -88,17 +78,18 @@ class ClassiqBaseModel(VersionedModel, ABC):
88
78
  )
89
79
 
90
80
  @pydantic.validator("types")
91
- def types_validator(
92
- cls, types: List[ConcreteStructDeclaration]
93
- ) -> List[ConcreteStructDeclaration]:
81
+ def types_validator(cls, types: List[StructDeclaration]) -> List[StructDeclaration]:
94
82
  if not is_list_unique([struct_type.name for struct_type in types]):
95
- raise ValueError(TYPE_LIBRARY_DUPLICATED_TYPE_NAMES)
83
+ raise ClassiqValueError(TYPE_LIBRARY_DUPLICATED_TYPE_NAMES)
96
84
 
97
85
  return types
98
86
 
99
87
 
100
88
  class ExecutionModel(ClassiqBaseModel):
101
- pass
89
+ circuit_outputs: ArithmeticIODict = pydantic.Field(
90
+ description="Mapping between a measured register name and its arithmetic type",
91
+ default_factory=dict,
92
+ )
102
93
 
103
94
 
104
95
  class SynthesisModel(ClassiqBaseModel):
@@ -106,7 +97,7 @@ class SynthesisModel(ClassiqBaseModel):
106
97
  All the relevant data for generating quantum circuit in one place.
107
98
  """
108
99
 
109
- kind: Literal["synthesis"] = get_discriminator_field("synthesis")
100
+ kind: Literal["synthesis"] = pydantic.Field(default="synthesis")
110
101
 
111
102
  # Must be validated before logic_flow
112
103
  functions: List[ConcreteFunctionDefinition] = pydantic.Field(
@@ -241,4 +232,5 @@ class SynthesisModel(ClassiqBaseModel):
241
232
  constants=self.constants,
242
233
  classical_execution_code=self.classical_execution_code,
243
234
  execution_preferences=self.execution_preferences,
235
+ circuit_outputs=self.main_func.outputs,
244
236
  )
@@ -21,6 +21,7 @@ from classiq.interface.hardware import Provider
21
21
  from classiq.interface.helpers.custom_pydantic_types import PydanticMachinePrecision
22
22
 
23
23
  from classiq._internals.enum_utils import StrEnum
24
+ from classiq.exceptions import ClassiqValueError
24
25
 
25
26
  if TYPE_CHECKING:
26
27
  VisualizationLevel: TypeAlias = Optional[int]
@@ -157,7 +158,7 @@ class Preferences(pydantic.BaseModel, extra=pydantic.Extra.forbid):
157
158
  if generation_timeout_seconds is None or optimization_timeout_seconds is None:
158
159
  return optimization_timeout_seconds
159
160
  if optimization_timeout_seconds >= generation_timeout_seconds:
160
- raise ValueError(
161
+ raise ClassiqValueError(
161
162
  f"Generation timeout ({generation_timeout_seconds})"
162
163
  f"is greater than or equal to "
163
164
  f"optimization timeout ({optimization_timeout_seconds}) "
@@ -176,7 +177,7 @@ class Preferences(pydantic.BaseModel, extra=pydantic.Extra.forbid):
176
177
  cls, output_format: PydanticConstrainedQuantumFormatList, values: Dict[str, Any]
177
178
  ) -> PydanticConstrainedQuantumFormatList:
178
179
  if len(output_format) != len(set(output_format)):
179
- raise ValueError(
180
+ raise ClassiqValueError(
180
181
  f"output_format={output_format}\n"
181
182
  "has at least one format that appears twice or more"
182
183
  )
@@ -196,7 +197,7 @@ class Preferences(pydantic.BaseModel, extra=pydantic.Extra.forbid):
196
197
  backend_name = values.get("backend_name")
197
198
  backend_service_provider = values.get("backend_service_provider")
198
199
  if (backend_name is None) != (backend_service_provider is None):
199
- raise ValueError(BACKEND_VALIDATION_ERROR_MESSAGE)
200
+ raise ClassiqValueError(BACKEND_VALIDATION_ERROR_MESSAGE)
200
201
  return values
201
202
 
202
203
  @property
@@ -11,6 +11,8 @@ from classiq.interface.generator.oracles.oracle_abc import (
11
11
  )
12
12
  from classiq.interface.generator.user_defined_function_params import CustomFunction
13
13
 
14
+ from classiq.exceptions import ClassiqValueError
15
+
14
16
  QubitState = str
15
17
 
16
18
 
@@ -39,12 +41,12 @@ class CustomOracle(OracleABC[QubitState]):
39
41
  if set(custom_oracle_params.input_decls.keys()) != set(
40
42
  custom_oracle_params.output_decls.keys()
41
43
  ):
42
- raise ValueError("Oracle IO names must be identical")
44
+ raise ClassiqValueError("Oracle IO names must be identical")
43
45
  if any(
44
46
  custom_oracle_params.output_decls[name].size != input_decl.size
45
47
  for name, input_decl in custom_oracle_params.input_decls.items()
46
48
  ):
47
- raise ValueError("Oracle IO sizes must be identical")
49
+ raise ClassiqValueError("Oracle IO sizes must be identical")
48
50
  return custom_oracle_params
49
51
 
50
52
  def _get_register_transputs(self) -> ArithmeticIODict:
@@ -60,10 +60,10 @@ class OracleABC(abc.ABC, FunctionParams, Generic[ProblemResultType]):
60
60
  pass
61
61
 
62
62
  def variables(self) -> List[RegisterUserInput]:
63
- return list(
63
+ return [
64
64
  RegisterUserInput.from_arithmetic_info(info=info, name=name)
65
65
  for name, info in self._inputs.items()
66
- )
66
+ ]
67
67
 
68
68
  def _check_indices(self, indices: IOQubitMapping) -> None:
69
69
  if set(indices.keys()) != {reg.name for reg in self.variables()}:
@@ -65,7 +65,7 @@ class ExponentiationSpecification(pydantic.BaseModel):
65
65
  cls, values: Dict[str, Any]
66
66
  ) -> Dict[str, Any]:
67
67
  if values.get("scaling") is None and values.get("max_depths") is None:
68
- raise ValueError("At least one specification must be provided.")
68
+ raise ClassiqValueError("At least one specification must be provided.")
69
69
  return values
70
70
 
71
71
 
@@ -131,7 +131,7 @@ class PhaseEstimation(FunctionParams):
131
131
  if not unitary_params.is_powerable():
132
132
  if isinstance(unitary_params, CustomFunction):
133
133
  raise ClassiqMismatchIOsError(CUSTOM_FUNCTIONS_IO_MISMATCH_ERROR)
134
- raise ValueError(
134
+ raise ClassiqValueError(
135
135
  f"Phase estimation of {unitary_params.discriminator()} is currently not supported."
136
136
  )
137
137
  return unitary_params
@@ -146,11 +146,13 @@ class PhaseEstimation(FunctionParams):
146
146
  return exponentiation_specification
147
147
  unitary_params = values.get("unitary_params")
148
148
  if not isinstance(unitary_params, Exponentiation):
149
- raise ValueError(
149
+ raise ClassiqValueError(
150
150
  "exponentiation_specification is only valid for Exponentiation unitary_params."
151
151
  )
152
152
  if exponentiation_specification.max_depths is not None and len(
153
153
  exponentiation_specification.max_depths
154
154
  ) != values.get("size"):
155
- raise ValueError("Length of max_depths must match the provided size.")
155
+ raise ClassiqValueError(
156
+ "Length of max_depths must match the provided size."
157
+ )
156
158
  return exponentiation_specification
@@ -12,10 +12,9 @@ from classiq.interface.generator.function_params import (
12
12
  from classiq.interface.helpers.hashable_pydantic_base_model import (
13
13
  HashablePydanticBaseModel,
14
14
  )
15
- from classiq.interface.helpers.pydantic_model_helpers import get_discriminator_field
16
15
 
17
16
  from classiq._internals.enum_utils import StrEnum
18
- from classiq.exceptions import ClassiqQSVMError
17
+ from classiq.exceptions import ClassiqQSVMError, ClassiqValueError
19
18
 
20
19
  VALID_PAULI_LETTERS = ("I", "X", "Y", "Z")
21
20
 
@@ -36,9 +35,7 @@ class QSVMFeatureMapDimensional(HashablePydanticBaseModel):
36
35
 
37
36
 
38
37
  class QSVMFeatureMapPauli(QSVMFeatureMapDimensional):
39
- map_type: Literal["pauli_feature_map"] = get_discriminator_field(
40
- "pauli_feature_map"
41
- )
38
+ map_type: Literal["pauli_feature_map"] = pydantic.Field(default="pauli_feature_map")
42
39
  reps: int = 2
43
40
  entanglement: QSVMFeatureMapEntanglement = QSVMFeatureMapEntanglement.LINEAR
44
41
  alpha: float = 2.0
@@ -51,15 +48,15 @@ class QSVMFeatureMapPauli(QSVMFeatureMapDimensional):
51
48
  # iterate every letter in every string in the list of paulis
52
49
  for s in paulis:
53
50
  if not all(map(VALID_PAULI_LETTERS.__contains__, s.upper())):
54
- raise ValueError(
51
+ raise ClassiqValueError(
55
52
  f"Invalid pauli string given: {s!r}. Expecting a combination of {VALID_PAULI_LETTERS}"
56
53
  )
57
54
  return list(map(str.upper, paulis))
58
55
 
59
56
 
60
57
  class QSVMFeatureMapBlochSphere(QSVMFeatureMapDimensional):
61
- map_type: Literal["bloch_sphere_feature_map"] = get_discriminator_field(
62
- "bloch_sphere_feature_map"
58
+ map_type: Literal["bloch_sphere_feature_map"] = pydantic.Field(
59
+ default="bloch_sphere_feature_map"
63
60
  )
64
61
 
65
62
 
@@ -24,6 +24,7 @@ from pydantic import BaseModel, Extra
24
24
 
25
25
  from classiq.interface.generator import function_param_list, function_params as f_params
26
26
  from classiq.interface.generator.arith.arithmetic import Arithmetic
27
+ from classiq.interface.generator.compiler_keywords import EXPANDED_KEYWORD
27
28
  from classiq.interface.generator.control_state import ControlState
28
29
  from classiq.interface.generator.function_params import (
29
30
  NAME_REGEX,
@@ -79,7 +80,7 @@ class WirePair(HashablePydanticBaseModel):
79
80
  out_wire: WireName
80
81
 
81
82
 
82
- SUFFIX_RANDOMIZER = random.Random() # nosec B311
83
+ SUFFIX_RANDOMIZER = random.Random()
83
84
 
84
85
 
85
86
  def split_wire_pair_to_wires(
@@ -90,8 +91,7 @@ def split_wire_pair_to_wires(
90
91
 
91
92
  def randomize_suffix(suffix_len: int = DEFAULT_SUFFIX_LEN) -> str:
92
93
  return "".join(
93
- SUFFIX_RANDOMIZER.choice(_ALPHANUM_CHARACTERS)
94
- for _ in range(suffix_len) # nosec B311
94
+ SUFFIX_RANDOMIZER.choice(_ALPHANUM_CHARACTERS) for _ in range(suffix_len)
95
95
  )
96
96
 
97
97
 
@@ -218,20 +218,23 @@ class SynthesisQuantumFunctionCall(BaseModel):
218
218
  if name is not None:
219
219
  match = re.fullmatch(pattern=NAME_REGEX, string=name)
220
220
  if match is None:
221
- raise ValueError(BAD_CALL_NAME_ERROR_MSG)
221
+ raise ClassiqValueError(BAD_CALL_NAME_ERROR_MSG)
222
222
  return name
223
223
 
224
224
  function = values.get("function")
225
225
 
226
226
  params = values.get("function_params")
227
- if isinstance(params, CustomFunction):
228
- if function == CustomFunction.discriminator() and params.name != "":
229
- function = params.name
227
+ if (
228
+ isinstance(params, CustomFunction)
229
+ and function == CustomFunction.discriminator()
230
+ and params.name != ""
231
+ ):
232
+ function = params.name
230
233
 
231
234
  suffix = f"{SUFFIX_MARKER}_{randomize_suffix()}"
232
235
  if not function or params is None:
233
236
  return name if name else suffix
234
- return f"{function}_{suffix}"
237
+ return f"{function.split(f'_{EXPANDED_KEYWORD}')[0]}_{suffix}"
235
238
 
236
239
  @pydantic.root_validator(pre=True)
237
240
  def validate_composite_name(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@@ -285,7 +288,7 @@ class SynthesisQuantumFunctionCall(BaseModel):
285
288
  if invalid_slicings:
286
289
  error_msg.append(f"{BAD_INPUT_SLICING_MSG}: {invalid_slicings}")
287
290
  if error_msg:
288
- raise ValueError("\n".join(error_msg))
291
+ raise ClassiqValueError("\n".join(error_msg))
289
292
 
290
293
  @pydantic.validator("strict_zero_ios")
291
294
  def _validate_arithmetic_cannot_strict_zero_ios(
@@ -352,7 +355,7 @@ class SynthesisQuantumFunctionCall(BaseModel):
352
355
  if not SynthesisQuantumFunctionCall._register_validate_slices(
353
356
  slices_dict[name], widths[name]
354
357
  ):
355
- raise ValueError(BAD_INPUT_SLICING_MSG)
358
+ raise ClassiqValueError(BAD_INPUT_SLICING_MSG)
356
359
 
357
360
  @staticmethod
358
361
  def _register_validate_slices(slices: List[slice], reg_width: int) -> bool:
@@ -384,7 +387,7 @@ class SynthesisQuantumFunctionCall(BaseModel):
384
387
  return dict()
385
388
  if isinstance(params, CustomFunction):
386
389
  if not isinstance(inputs, dict):
387
- raise ValueError(CUSTOM_FUNCTION_SINGLE_IO_ERROR)
390
+ raise ClassiqValueError(CUSTOM_FUNCTION_SINGLE_IO_ERROR)
388
391
  return inputs
389
392
 
390
393
  if isinstance(inputs, str):
@@ -442,7 +445,7 @@ class SynthesisQuantumFunctionCall(BaseModel):
442
445
  if invalid_slicings:
443
446
  error_msg.append(f"{BAD_OUTPUT_SLICING_MSG}: {invalid_slicings}")
444
447
  if error_msg:
445
- raise ValueError("\n".join(error_msg))
448
+ raise ClassiqValueError("\n".join(error_msg))
446
449
 
447
450
  @pydantic.validator("outputs")
448
451
  def _validate_outputs(cls, outputs: IOType, values: Dict[str, Any]) -> IOType:
@@ -454,7 +457,7 @@ class SynthesisQuantumFunctionCall(BaseModel):
454
457
  return outputs
455
458
  if isinstance(params, CustomFunction):
456
459
  if not isinstance(outputs, dict):
457
- raise ValueError(CUSTOM_FUNCTION_SINGLE_IO_ERROR)
460
+ raise ClassiqValueError(CUSTOM_FUNCTION_SINGLE_IO_ERROR)
458
461
  return outputs
459
462
 
460
463
  if isinstance(outputs, str):
@@ -494,7 +497,7 @@ class SynthesisQuantumFunctionCall(BaseModel):
494
497
  if power != 1 and not function_params.is_powerable(
495
498
  values.get("strict_zero_ios")
496
499
  ):
497
- raise ValueError("Cannot power this operator")
500
+ raise ClassiqValueError("Cannot power this operator")
498
501
  return power
499
502
 
500
503
  @staticmethod
@@ -519,7 +522,7 @@ class SynthesisQuantumFunctionCall(BaseModel):
519
522
  io_wire=io_wire,
520
523
  function_name=type(params).__name__,
521
524
  )
522
- raise ValueError(error_message)
525
+ raise ClassiqValueError(error_message)
523
526
 
524
527
  @staticmethod
525
528
  def _get_invalid_ios(
@@ -610,7 +613,9 @@ class SynthesisQuantumFunctionCall(BaseModel):
610
613
  control_state.name in self.inputs_dict
611
614
  or control_state.name in self.outputs_dict
612
615
  ):
613
- raise ValueError(f"Control name: {control_state.name} already exists")
616
+ raise ClassiqValueError(
617
+ f"Control name: {control_state.name} already exists"
618
+ )
614
619
 
615
620
  inputs, outputs = dict(self.inputs_dict), dict(self.outputs_dict)
616
621
  inputs.update({control_state.name: input_wire})
@@ -6,7 +6,7 @@ from typing import Dict, List, Optional, Tuple, Union
6
6
  import pydantic
7
7
  from typing_extensions import TypeAlias
8
8
 
9
- from classiq.interface.executor import quantum_program
9
+ from classiq.interface.executor import quantum_code
10
10
  from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
11
11
  from classiq.interface.executor.register_initialization import RegisterInitialization
12
12
  from classiq.interface.generator.circuit_code.circuit_code import CircuitCodeInterface
@@ -21,7 +21,7 @@ from classiq.interface.generator.generated_circuit_data import (
21
21
  GeneratedCircuitData,
22
22
  )
23
23
  from classiq.interface.generator.hardware.hardware_data import SynthesisHardwareData
24
- from classiq.interface.generator.model.model import ExecutionModel, SynthesisModel
24
+ from classiq.interface.generator.model.model import ExecutionModel
25
25
  from classiq.interface.generator.synthesis_metadata.synthesis_duration import (
26
26
  SynthesisStepDurations,
27
27
  )
@@ -51,11 +51,11 @@ def get_uuid_as_str() -> str:
51
51
  return str(uuid.uuid4())
52
52
 
53
53
 
54
- class GeneratedCircuit(VersionedModel, CircuitCodeInterface):
54
+ class QuantumProgram(VersionedModel, CircuitCodeInterface):
55
55
  hardware_data: SynthesisHardwareData
56
56
  initial_values: Optional[InitialConditions]
57
57
  data: GeneratedCircuitData
58
- model: SynthesisModel
58
+ model: ExecutionModel
59
59
  transpiled_circuit: Optional[TranspiledCircuitData]
60
60
  creation_time: str = pydantic.Field(default_factory=datetime.utcnow().isoformat)
61
61
  synthesis_duration: Optional[SynthesisStepDurations]
@@ -81,15 +81,15 @@ class GeneratedCircuit(VersionedModel, CircuitCodeInterface):
81
81
  )
82
82
  return self.program_circuit.get_code(instruction_set), instruction_set
83
83
 
84
- def to_base_program(self) -> quantum_program.QuantumBaseProgram:
84
+ def to_base_program(self) -> quantum_code.QuantumBaseCode:
85
85
  code, syntax = self._default_program_code()
86
- return quantum_program.QuantumBaseProgram(code=code, syntax=syntax)
86
+ return quantum_code.QuantumBaseCode(code=code, syntax=syntax)
87
87
 
88
88
  def to_program(
89
89
  self,
90
90
  initial_values: Optional[InitialConditions] = None,
91
91
  instruction_set: Optional[QuantumInstructionSet] = None,
92
- ) -> quantum_program.QuantumProgram:
92
+ ) -> quantum_code.QuantumCode:
93
93
  initial_values = initial_values or self.initial_values
94
94
 
95
95
  if instruction_set is not None:
@@ -106,7 +106,7 @@ class GeneratedCircuit(VersionedModel, CircuitCodeInterface):
106
106
  )
107
107
  else:
108
108
  registers_initialization = None
109
- return quantum_program.QuantumProgram(
109
+ return quantum_code.QuantumCode(
110
110
  code=code,
111
111
  syntax=syntax,
112
112
  output_qubits_map=self.data.qubit_mapping.physical_outputs,
@@ -136,7 +136,7 @@ class GeneratedCircuit(VersionedModel, CircuitCodeInterface):
136
136
 
137
137
  def save_results(self, filename: Optional[Union[str, Path]] = None) -> None:
138
138
  """
139
- Saves generated circuit results as json.
139
+ Saves quantum program results as json.
140
140
  Parameters:
141
141
  filename (Union[str, Path]): Optional, path + filename of file.
142
142
  If filename supplied add `.json` suffix.
@@ -151,7 +151,7 @@ class GeneratedCircuit(VersionedModel, CircuitCodeInterface):
151
151
  file.write(self.json(indent=4))
152
152
 
153
153
  @classmethod
154
- def from_qprog(cls, qprog: str) -> "GeneratedCircuit":
154
+ def from_qprog(cls, qprog: str) -> "QuantumProgram":
155
155
  return cls.parse_raw(qprog)
156
156
 
157
157
  @property
@@ -165,7 +165,3 @@ class GeneratedCircuit(VersionedModel, CircuitCodeInterface):
165
165
  if self.transpiled_circuit and self._can_use_transpiled_code
166
166
  else self
167
167
  )
168
-
169
- @property
170
- def execution_model(self) -> ExecutionModel:
171
- return self.model.classical_model()
@@ -4,6 +4,8 @@ from typing import Any, Dict, Generic, Optional, TypeVar
4
4
  import pydantic
5
5
  from pydantic.generics import GenericModel
6
6
 
7
+ from classiq.exceptions import ClassiqValueError
8
+
7
9
  RangeType = TypeVar("RangeType", int, float)
8
10
 
9
11
  # math.isclose is symmetric and well equipped to avoid unwanted scenarios while numpy's isn't
@@ -30,7 +32,7 @@ class Range(GenericModel, Generic[RangeType]):
30
32
  and upper_bound is not None
31
33
  and lower_bound > upper_bound
32
34
  ):
33
- raise ValueError("lower bound must not be greater than upper bound")
35
+ raise ClassiqValueError("lower bound must not be greater than upper bound")
34
36
 
35
37
  return values
36
38
 
@@ -3,6 +3,8 @@ from typing import Match, Optional, Tuple
3
3
 
4
4
  from classiq.interface.generator.function_params import NAME_REGEX
5
5
 
6
+ from classiq.exceptions import ClassiqValueError
7
+
6
8
  NAME = "name"
7
9
  SLICING = "slicing"
8
10
  SEPARATOR = ":"
@@ -33,9 +35,12 @@ def get_slice(slicing: Optional[str]) -> slice:
33
35
 
34
36
  if len(split) == 1:
35
37
  index_block = split[0]
36
- # failing int raises ValueError which Pydantic captures
37
- # RegEx matching should deem this scenario impossible
38
- index = int(index_block)
38
+ try:
39
+ index = int(index_block)
40
+ except ValueError:
41
+ raise ClassiqValueError(
42
+ f"Index {index_block!r} is not an integer"
43
+ ) from None
39
44
  stop = index + 1 if index != -1 else None
40
45
  return slice(index, stop, None)
41
46
 
@@ -9,6 +9,8 @@ from classiq.interface.generator.standard_gates.standard_gates import (
9
9
  _StandardGate,
10
10
  )
11
11
 
12
+ from classiq.exceptions import ClassiqValueError
13
+
12
14
  CONTROLLED_GATE_CONTROL: str = "CTRL"
13
15
  CONTROLLED_GATE_TARGET: str = DEFAULT_STANDARD_GATE_ARG_NAME
14
16
  DEFAULT_NUM_CTRL_QUBITS: int = 1
@@ -58,12 +60,12 @@ class ControlledGateWithState(ControlledGate): # type: ignore[misc]
58
60
  ctrl_state = ctrl_state if ctrl_state is not None else "1" * num_ctrl_qubits
59
61
 
60
62
  if isinstance(ctrl_state, str) and len(ctrl_state) != num_ctrl_qubits:
61
- raise ValueError(
63
+ raise ClassiqValueError(
62
64
  f"Invalid control state: {ctrl_state!r}. "
63
65
  f"Expected {num_ctrl_qubits} qubits"
64
66
  )
65
67
  elif isinstance(ctrl_state, int) and ctrl_state >= 2**num_ctrl_qubits:
66
- raise ValueError(
68
+ raise ClassiqValueError(
67
69
  f"Invalid control state: {ctrl_state}. "
68
70
  f"Expected value between 0 and {2**num_ctrl_qubits-1}"
69
71
  )
@@ -5,6 +5,7 @@ from classiq.interface.generator.preferences.optimization import (
5
5
  )
6
6
 
7
7
  from classiq._internals.enum_utils import StrEnum
8
+ from classiq.exceptions import ClassiqValueError
8
9
 
9
10
  _AMPLITUDE_SUPPORTING_METRICS: FrozenSet = frozenset(
10
11
  {"L2", "L1", "MAX_PROBABILITY", "TOTAL_VARIATION"}
@@ -30,7 +31,7 @@ class Metrics(StrEnum):
30
31
  try:
31
32
  return Metrics(sp_opt_method.value)
32
33
  except ValueError:
33
- raise ValueError(
34
+ raise ClassiqValueError(
34
35
  f"Failed to convert {sp_opt_method} to an error metric"
35
36
  ) from None
36
37
 
@@ -21,6 +21,8 @@ from classiq.interface.generator.validations.validator_functions import (
21
21
  validate_amplitudes,
22
22
  )
23
23
 
24
+ from classiq.exceptions import ClassiqValueError
25
+
24
26
 
25
27
  class StatePreparation(StatePreparationABC):
26
28
  amplitudes: Optional[Amplitudes] = pydantic.Field(
@@ -46,7 +48,7 @@ class StatePreparation(StatePreparationABC):
46
48
  if amplitudes.ndim == 1:
47
49
  return validate_amplitudes(tuple(amplitudes))
48
50
 
49
- raise ValueError(
51
+ raise ClassiqValueError(
50
52
  "Invalid amplitudes were given, please ensure the amplitude is a vector of float in the form of either tuple or list or numpy array"
51
53
  )
52
54
 
@@ -64,7 +66,7 @@ class StatePreparation(StatePreparationABC):
64
66
  if probabilities.ndim == 1:
65
67
  return PMF(pmf=probabilities.tolist())
66
68
 
67
- raise ValueError(
69
+ raise ClassiqValueError(
68
70
  "Invalid probabilities were given, please ensure the probabilities is a vector of float in the form of either tuple or list or numpy array"
69
71
  )
70
72
 
@@ -80,7 +82,7 @@ class StatePreparation(StatePreparationABC):
80
82
  if not Metrics(metric).supports_amplitudes
81
83
  }
82
84
  if unsupported_metrics:
83
- raise ValueError(
85
+ raise ClassiqValueError(
84
86
  f"{unsupported_metrics} are not supported for amplitude preparation"
85
87
  )
86
88
  return error_metric
@@ -93,7 +95,7 @@ class StatePreparation(StatePreparationABC):
93
95
  amplitudes = values.get("amplitudes")
94
96
  probabilities = values.get("probabilities")
95
97
  if amplitudes is not None and probabilities is not None:
96
- raise ValueError(
98
+ raise ClassiqValueError(
97
99
  "StatePreparation can't get both probabilities and amplitudes"
98
100
  )
99
101
  return values
@@ -102,5 +104,5 @@ class StatePreparation(StatePreparationABC):
102
104
  def num_state_qubits(self) -> int:
103
105
  distribution = self.probabilities or self.amplitudes
104
106
  if distribution is None:
105
- raise ValueError("Must have either probabilities or amplitudes")
107
+ raise ClassiqValueError("Must have either probabilities or amplitudes")
106
108
  return num_of_qubits(distribution)