classiq 0.43.2__py3-none-any.whl → 0.44.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 (112) hide show
  1. classiq/__init__.py +7 -1
  2. classiq/_internals/client.py +4 -7
  3. classiq/_internals/host_checker.py +34 -12
  4. classiq/_internals/jobs.py +2 -2
  5. classiq/applications/chemistry/chemistry_model_constructor.py +12 -6
  6. classiq/applications/combinatorial_helpers/allowed_constraints.py +4 -1
  7. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
  8. classiq/applications/finance/finance_model_constructor.py +3 -2
  9. classiq/applications/grover/grover_model_constructor.py +7 -5
  10. classiq/applications/hamiltonian/__init__.py +0 -0
  11. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  12. classiq/applications/qnn/qlayer.py +1 -1
  13. classiq/exceptions.py +4 -0
  14. classiq/interface/_version.py +1 -1
  15. classiq/interface/ast_node.py +1 -18
  16. classiq/interface/backend/backend_preferences.py +15 -16
  17. classiq/interface/backend/ionq/ionq_quantum_program.py +1 -1
  18. classiq/interface/backend/pydantic_backend.py +0 -5
  19. classiq/interface/backend/quantum_backend_providers.py +3 -2
  20. classiq/interface/chemistry/operator.py +5 -1
  21. classiq/interface/debug_info/__init__.py +0 -0
  22. classiq/interface/debug_info/debug_info.py +32 -0
  23. classiq/interface/executor/execution_preferences.py +1 -45
  24. classiq/interface/executor/result.py +25 -12
  25. classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
  26. classiq/interface/generator/application_apis/chemistry_declarations.py +78 -60
  27. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +19 -10
  28. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  29. classiq/interface/generator/application_apis/finance_declarations.py +36 -22
  30. classiq/interface/generator/application_apis/qsvm_declarations.py +21 -15
  31. classiq/interface/generator/arith/arithmetic_expression_abc.py +21 -1
  32. classiq/interface/generator/arith/binary_ops.py +5 -4
  33. classiq/interface/generator/arith/extremum_operations.py +43 -19
  34. classiq/interface/generator/constant.py +1 -1
  35. classiq/interface/generator/expressions/atomic_expression_functions.py +1 -0
  36. classiq/interface/generator/expressions/expression_constants.py +3 -1
  37. classiq/interface/generator/expressions/qmod_qarray_proxy.py +52 -66
  38. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +35 -0
  39. classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
  40. classiq/interface/generator/functions/builtins/core_library/__init__.py +4 -2
  41. classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +41 -41
  42. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +52 -42
  43. classiq/interface/generator/functions/builtins/open_lib_functions.py +1095 -3347
  44. classiq/interface/generator/functions/builtins/quantum_operators.py +9 -22
  45. classiq/interface/generator/functions/classical_function_declaration.py +14 -6
  46. classiq/interface/generator/functions/classical_type.py +7 -76
  47. classiq/interface/generator/functions/concrete_types.py +55 -0
  48. classiq/interface/generator/functions/function_declaration.py +10 -10
  49. classiq/interface/generator/functions/type_name.py +104 -0
  50. classiq/interface/generator/generated_circuit_data.py +3 -3
  51. classiq/interface/generator/model/model.py +11 -0
  52. classiq/interface/generator/model/preferences/preferences.py +5 -0
  53. classiq/interface/generator/quantum_function_call.py +3 -0
  54. classiq/interface/generator/quantum_program.py +2 -2
  55. classiq/interface/generator/register_role.py +7 -1
  56. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +1 -3
  57. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +1 -2
  58. classiq/interface/generator/types/qstruct_declaration.py +17 -0
  59. classiq/interface/generator/types/struct_declaration.py +1 -1
  60. classiq/interface/helpers/validation_helpers.py +1 -17
  61. classiq/interface/ide/visual_model.py +9 -2
  62. classiq/interface/interface_version.py +1 -0
  63. classiq/interface/model/bind_operation.py +25 -5
  64. classiq/interface/model/classical_parameter_declaration.py +8 -5
  65. classiq/interface/model/control.py +5 -5
  66. classiq/interface/model/handle_binding.py +185 -12
  67. classiq/interface/model/inplace_binary_operation.py +16 -4
  68. classiq/interface/model/model.py +28 -5
  69. classiq/interface/model/native_function_definition.py +8 -4
  70. classiq/interface/model/parameter.py +14 -0
  71. classiq/interface/model/port_declaration.py +20 -2
  72. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +21 -6
  73. classiq/interface/model/quantum_expressions/arithmetic_operation.py +30 -6
  74. classiq/interface/model/quantum_expressions/quantum_expression.py +4 -9
  75. classiq/interface/model/quantum_function_call.py +135 -192
  76. classiq/interface/model/quantum_function_declaration.py +147 -165
  77. classiq/interface/model/quantum_lambda_function.py +24 -6
  78. classiq/interface/model/quantum_statement.py +34 -8
  79. classiq/interface/model/quantum_type.py +61 -10
  80. classiq/interface/model/quantum_variable_declaration.py +1 -1
  81. classiq/interface/model/statement_block.py +2 -0
  82. classiq/interface/model/validation_handle.py +7 -0
  83. classiq/interface/server/global_versions.py +4 -4
  84. classiq/interface/server/routes.py +2 -0
  85. classiq/interface/source_reference.py +59 -0
  86. classiq/qmod/__init__.py +2 -3
  87. classiq/qmod/builtins/functions.py +39 -11
  88. classiq/qmod/builtins/operations.py +171 -40
  89. classiq/qmod/declaration_inferrer.py +99 -56
  90. classiq/qmod/expression_query.py +1 -1
  91. classiq/qmod/model_state_container.py +2 -0
  92. classiq/qmod/native/pretty_printer.py +71 -53
  93. classiq/qmod/pretty_print/pretty_printer.py +98 -52
  94. classiq/qmod/qfunc.py +11 -5
  95. classiq/qmod/qmod_parameter.py +1 -2
  96. classiq/qmod/qmod_variable.py +364 -172
  97. classiq/qmod/quantum_callable.py +3 -3
  98. classiq/qmod/quantum_expandable.py +119 -65
  99. classiq/qmod/quantum_function.py +15 -3
  100. classiq/qmod/semantics/annotation.py +12 -13
  101. classiq/qmod/semantics/error_manager.py +36 -10
  102. classiq/qmod/semantics/static_semantics_visitor.py +163 -75
  103. classiq/qmod/semantics/validation/func_call_validation.py +42 -96
  104. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  105. classiq/qmod/semantics/validation/types_validation.py +108 -1
  106. classiq/qmod/type_attribute_remover.py +32 -0
  107. classiq/qmod/utilities.py +26 -5
  108. {classiq-0.43.2.dist-info → classiq-0.44.0.dist-info}/METADATA +3 -3
  109. {classiq-0.43.2.dist-info → classiq-0.44.0.dist-info}/RECORD +111 -99
  110. classiq/qmod/qmod_struct.py +0 -13
  111. /classiq/{interface/ide/show.py → show.py} +0 -0
  112. {classiq-0.43.2.dist-info → classiq-0.44.0.dist-info}/WHEEL +0 -0
@@ -1,15 +1,11 @@
1
- from datetime import timedelta
2
- from typing import Any, Dict, Optional
1
+ from typing import Optional
3
2
 
4
3
  import pydantic
5
4
 
6
5
  from classiq.interface.backend.backend_preferences import (
7
- AWS_DEFAULT_JOB_TIMEOUT_SECONDS,
8
- AwsBackendPreferences,
9
6
  BackendPreferencesTypes,
10
7
  backend_preferences_field,
11
8
  )
12
- from classiq.interface.backend.pydantic_backend import MAX_EXECUTION_TIMEOUT_SECONDS
13
9
  from classiq.interface.backend.quantum_backend_providers import (
14
10
  ClassiqSimulatorBackendNames,
15
11
  )
@@ -21,17 +17,6 @@ from classiq.interface.generator.model.preferences.randomness import create_rand
21
17
  from classiq.interface.generator.noise_properties import NoiseProperties
22
18
 
23
19
  from classiq._internals.enum_utils import ReprEnum
24
- from classiq.exceptions import ClassiqValueError
25
-
26
- DIFFERENT_TIMEOUT_MSG = (
27
- "Timeout is defined differently in the execution preferences and the "
28
- "AWS Backend Preferences."
29
- )
30
-
31
- TIMEOUT_LARGE_FOR_AWS_MSG = (
32
- "Timeout is larger than the current allowed limit of "
33
- f"{timedelta(MAX_EXECUTION_TIMEOUT_SECONDS)}"
34
- )
35
20
 
36
21
 
37
22
  class QaeWithQpeEstimationMethod(int, ReprEnum):
@@ -40,11 +25,6 @@ class QaeWithQpeEstimationMethod(int, ReprEnum):
40
25
 
41
26
 
42
27
  class ExecutionPreferences(pydantic.BaseModel):
43
- timeout_sec: Optional[pydantic.PositiveInt] = pydantic.Field(
44
- default=None,
45
- description="If set, limits the execution runtime. Value is in seconds. "
46
- "Not supported on all platforms.",
47
- )
48
28
  noise_properties: Optional[NoiseProperties] = pydantic.Field(
49
29
  default=None, description="Properties of the noise in the circuit"
50
30
  )
@@ -66,30 +46,6 @@ class ExecutionPreferences(pydantic.BaseModel):
66
46
  description="The job name",
67
47
  )
68
48
 
69
- def __init__(self, **kwargs: Any) -> None:
70
- super().__init__(**kwargs)
71
-
72
- @pydantic.validator("backend_preferences", always=True)
73
- def validate_timeout_for_aws(
74
- cls, backend_preferences: BackendPreferencesTypes, values: Dict[str, Any]
75
- ) -> BackendPreferencesTypes:
76
- timeout = values.get("timeout_sec", None)
77
- if (
78
- not isinstance(backend_preferences, AwsBackendPreferences)
79
- or timeout is None
80
- ):
81
- return backend_preferences
82
- if (
83
- timeout != backend_preferences.job_timeout
84
- and backend_preferences.job_timeout != AWS_DEFAULT_JOB_TIMEOUT_SECONDS
85
- ):
86
- raise ClassiqValueError(DIFFERENT_TIMEOUT_MSG)
87
- if timeout > MAX_EXECUTION_TIMEOUT_SECONDS:
88
- raise ClassiqValueError(TIMEOUT_LARGE_FOR_AWS_MSG)
89
-
90
- backend_preferences.job_timeout = timeout
91
- return backend_preferences
92
-
93
49
 
94
50
  __all__ = [
95
51
  "ExecutionPreferences",
@@ -2,6 +2,7 @@ import functools
2
2
  import operator
3
3
  from collections import defaultdict
4
4
  from typing import (
5
+ TYPE_CHECKING,
5
6
  Any,
6
7
  DefaultDict,
7
8
  Dict,
@@ -32,7 +33,7 @@ _UNAVAILABLE_OUTPUT_ERROR_MSG: str = "Requested output doesn't exist in the circ
32
33
 
33
34
  State: TypeAlias = str
34
35
  Name: TypeAlias = str
35
- RegisterValue: TypeAlias = Union[float, int]
36
+ RegisterValue: TypeAlias = Union[float, int, list, dict]
36
37
  MeasuredShots: TypeAlias = pydantic.NonNegativeInt
37
38
  ParsedState: TypeAlias = Mapping[Name, RegisterValue]
38
39
  ParsedStates: TypeAlias = Mapping[State, ParsedState]
@@ -60,6 +61,7 @@ class SimulatedState(BaseModel):
60
61
  return self.state[item]
61
62
 
62
63
 
64
+ SimulatedState.update_forward_refs(RegisterValue=RegisterValue)
63
65
  ParsedStateVector: TypeAlias = List[SimulatedState]
64
66
 
65
67
 
@@ -122,6 +124,23 @@ def get_parsed_counts(counts: Counts, parsed_states: ParsedStates) -> ParsedCoun
122
124
  return sorted(parsed_counts, key=lambda k: k.shots, reverse=True)
123
125
 
124
126
 
127
+ def prepare_parsed_state_vector(
128
+ state_vector: StateVector, parsed_state_vector_states: ParsedStates
129
+ ) -> Optional[ParsedStateVector]:
130
+ if not state_vector:
131
+ return None
132
+
133
+ parsed_state_vector = [
134
+ SimulatedState(
135
+ state=parsed_state_vector_states[bitstring],
136
+ bitstring=bitstring,
137
+ amplitude=complex(amplitude_str),
138
+ )
139
+ for bitstring, amplitude_str in state_vector.items()
140
+ ]
141
+ return sorted(parsed_state_vector, key=lambda k: abs(k.amplitude), reverse=True)
142
+
143
+
125
144
  class ExecutionDetails(BaseModel, QmodPyObject):
126
145
  vendor_format_result: Dict[str, Any] = pydantic.Field(
127
146
  ..., description="Result in proprietary vendor format"
@@ -184,17 +203,9 @@ class ExecutionDetails(BaseModel, QmodPyObject):
184
203
 
185
204
  @property
186
205
  def parsed_state_vector(self) -> Optional[ParsedStateVector]:
187
- if not self.state_vector:
188
- return None
189
- parsed_state_vector = [
190
- SimulatedState(
191
- state=self.parsed_state_vector_states[bitstring],
192
- bitstring=bitstring,
193
- amplitude=complex(amplitude_str),
194
- )
195
- for bitstring, amplitude_str in self.state_vector.items()
196
- ]
197
- return sorted(parsed_state_vector, key=lambda k: abs(k.amplitude), reverse=True)
206
+ return prepare_parsed_state_vector(
207
+ self.state_vector, self.parsed_state_vector_states
208
+ )
198
209
 
199
210
  def flip_execution_counts_bitstring(self) -> None:
200
211
  """Backends should return result count bitstring in right to left form"""
@@ -261,6 +272,8 @@ class ExecutionDetails(BaseModel, QmodPyObject):
261
272
  lsb_right=False
262
273
  ).items():
263
274
  value = value_from_str_bin(binary_string=results_binary_key)
275
+ if TYPE_CHECKING:
276
+ assert isinstance(value, float)
264
277
  register_output[value] = register_output.get(value, 0) + counts
265
278
 
266
279
  return register_output
@@ -2,13 +2,16 @@ from classiq.interface.generator.functions.classical_function_declaration import
2
2
  ClassicalFunctionDeclaration,
3
3
  )
4
4
  from classiq.interface.generator.functions.classical_type import Integer, Real
5
+ from classiq.interface.model.classical_parameter_declaration import (
6
+ ClassicalParameterDeclaration,
7
+ )
5
8
 
6
9
  qft_const_adder_phase = ClassicalFunctionDeclaration(
7
10
  name="qft_const_adder_phase",
8
- param_decls={
9
- "bit_index": Integer(),
10
- "value": Integer(),
11
- "reg_len": Integer(),
12
- },
11
+ positional_parameters=[
12
+ ClassicalParameterDeclaration(name="bit_index", classical_type=Integer()),
13
+ ClassicalParameterDeclaration(name="value", classical_type=Integer()),
14
+ ClassicalParameterDeclaration(name="reg_len", classical_type=Integer()),
15
+ ],
13
16
  return_type=Real(),
14
17
  )
@@ -10,43 +10,44 @@ from classiq.interface.generator.functions.classical_type import (
10
10
  ClassicalList,
11
11
  Integer,
12
12
  Real,
13
- Struct,
14
- TypeName,
15
13
  VQEResult,
16
14
  )
17
15
  from classiq.interface.generator.functions.port_declaration import (
18
16
  PortDeclarationDirection,
19
17
  )
18
+ from classiq.interface.generator.functions.type_name import Struct, TypeName
20
19
  from classiq.interface.generator.types.struct_declaration import StructDeclaration
20
+ from classiq.interface.model.classical_parameter_declaration import (
21
+ ClassicalParameterDeclaration,
22
+ )
21
23
  from classiq.interface.model.port_declaration import PortDeclaration
22
24
  from classiq.interface.model.quantum_function_declaration import (
23
- QuantumFunctionDeclaration,
25
+ NamedParamsQuantumFunctionDeclaration,
24
26
  )
25
27
 
26
- MOLECULE_PROBLEM_PARAM = {"molecule_problem": Struct(name="MoleculeProblem")}
28
+ MOLECULE_PROBLEM_PARAM = ClassicalParameterDeclaration(
29
+ name="molecule_problem", classical_type=Struct(name="MoleculeProblem")
30
+ )
27
31
  MOLECULE_PROBLEM_SIZE = "get_field(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'), 'len')"
28
- MOLECULE_PROBLEM_PORT = {
29
- "qbv": PortDeclaration(
30
- name="qbv",
31
- direction=PortDeclarationDirection.Inout,
32
- size=Expression(
33
- expr=MOLECULE_PROBLEM_SIZE,
34
- ),
35
- )
36
- }
32
+ MOLECULE_PROBLEM_PORT = PortDeclaration(
33
+ name="qbv",
34
+ direction=PortDeclarationDirection.Inout,
35
+ size=Expression(
36
+ expr=MOLECULE_PROBLEM_SIZE,
37
+ ),
38
+ )
37
39
 
38
- FOCK_HAMILTONIAN_PROBLEM_PARAM = {
39
- "fock_hamiltonian_problem": Struct(name="FockHamiltonianProblem")
40
- }
40
+ FOCK_HAMILTONIAN_PROBLEM_PARAM = ClassicalParameterDeclaration(
41
+ name="fock_hamiltonian_problem",
42
+ classical_type=Struct(name="FockHamiltonianProblem"),
43
+ )
41
44
  FOCK_HAMILTONIAN_SIZE = "get_field(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'), 'len')"
42
45
 
43
- FOCK_HAMILTONIAN_PROBLEM_PORT = {
44
- "qbv": PortDeclaration(
45
- name="qbv",
46
- direction=PortDeclarationDirection.Inout,
47
- size=Expression(expr=FOCK_HAMILTONIAN_SIZE),
48
- )
49
- }
46
+ FOCK_HAMILTONIAN_PROBLEM_PORT = PortDeclaration(
47
+ name="qbv",
48
+ direction=PortDeclarationDirection.Inout,
49
+ size=Expression(expr=FOCK_HAMILTONIAN_SIZE),
50
+ )
50
51
 
51
52
 
52
53
  class ChemistryProblemType(Enum):
@@ -54,59 +55,63 @@ class ChemistryProblemType(Enum):
54
55
  FockHamiltonianProblem = "fock_hamiltonian_problem"
55
56
 
56
57
 
57
- MOLECULE_UCC_ANSATZ = QuantumFunctionDeclaration(
58
+ MOLECULE_UCC_ANSATZ = NamedParamsQuantumFunctionDeclaration(
58
59
  name="molecule_ucc",
59
- param_decls={
60
- **MOLECULE_PROBLEM_PARAM,
61
- "excitations": ClassicalList(element_type=Integer()),
62
- },
63
- port_declarations=MOLECULE_PROBLEM_PORT,
60
+ positional_arg_declarations=[
61
+ MOLECULE_PROBLEM_PARAM,
62
+ ClassicalParameterDeclaration(
63
+ name="excitations", classical_type=ClassicalList(element_type=Integer())
64
+ ),
65
+ MOLECULE_PROBLEM_PORT,
66
+ ],
64
67
  )
65
68
 
66
69
 
67
- MOLECULE_HVA_ANSATZ = QuantumFunctionDeclaration(
70
+ MOLECULE_HVA_ANSATZ = NamedParamsQuantumFunctionDeclaration(
68
71
  name="molecule_hva",
69
- param_decls={
70
- **MOLECULE_PROBLEM_PARAM,
71
- "reps": Integer(),
72
- },
73
- port_declarations=MOLECULE_PROBLEM_PORT,
72
+ positional_arg_declarations=[
73
+ MOLECULE_PROBLEM_PARAM,
74
+ ClassicalParameterDeclaration(name="reps", classical_type=Integer()),
75
+ MOLECULE_PROBLEM_PORT,
76
+ ],
74
77
  )
75
78
 
76
79
 
77
- MOLECULE_HARTREE_FOCK = QuantumFunctionDeclaration(
80
+ MOLECULE_HARTREE_FOCK = NamedParamsQuantumFunctionDeclaration(
78
81
  name="molecule_hartree_fock",
79
- param_decls={
80
- **MOLECULE_PROBLEM_PARAM,
81
- },
82
- port_declarations=MOLECULE_PROBLEM_PORT,
82
+ positional_arg_declarations=[
83
+ MOLECULE_PROBLEM_PARAM,
84
+ MOLECULE_PROBLEM_PORT,
85
+ ],
83
86
  )
84
87
 
85
88
 
86
- FOCK_HAMILTONIAN_UCC_ANSATZ = QuantumFunctionDeclaration(
89
+ FOCK_HAMILTONIAN_UCC_ANSATZ = NamedParamsQuantumFunctionDeclaration(
87
90
  name="fock_hamiltonian_ucc",
88
- param_decls={
89
- **FOCK_HAMILTONIAN_PROBLEM_PARAM,
90
- "excitations": ClassicalList(element_type=Integer()),
91
- },
92
- port_declarations=FOCK_HAMILTONIAN_PROBLEM_PORT,
91
+ positional_arg_declarations=[
92
+ FOCK_HAMILTONIAN_PROBLEM_PARAM,
93
+ ClassicalParameterDeclaration(
94
+ name="excitations", classical_type=ClassicalList(element_type=Integer())
95
+ ),
96
+ FOCK_HAMILTONIAN_PROBLEM_PORT,
97
+ ],
93
98
  )
94
99
 
95
- FOCK_HAMILTONIAN_HVA_ANSATZ = QuantumFunctionDeclaration(
100
+ FOCK_HAMILTONIAN_HVA_ANSATZ = NamedParamsQuantumFunctionDeclaration(
96
101
  name="fock_hamiltonian_hva",
97
- param_decls={
98
- **FOCK_HAMILTONIAN_PROBLEM_PARAM,
99
- "reps": Integer(),
100
- },
101
- port_declarations=FOCK_HAMILTONIAN_PROBLEM_PORT,
102
+ positional_arg_declarations=[
103
+ FOCK_HAMILTONIAN_PROBLEM_PARAM,
104
+ ClassicalParameterDeclaration(name="reps", classical_type=Integer()),
105
+ FOCK_HAMILTONIAN_PROBLEM_PORT,
106
+ ],
102
107
  )
103
108
 
104
- FOCK_HAMILTONIAN_HARTREE_FOCK = QuantumFunctionDeclaration(
109
+ FOCK_HAMILTONIAN_HARTREE_FOCK = NamedParamsQuantumFunctionDeclaration(
105
110
  name="fock_hamiltonian_hartree_fock",
106
- param_decls={
107
- **FOCK_HAMILTONIAN_PROBLEM_PARAM,
108
- },
109
- port_declarations=FOCK_HAMILTONIAN_PROBLEM_PORT,
111
+ positional_arg_declarations=[
112
+ FOCK_HAMILTONIAN_PROBLEM_PARAM,
113
+ FOCK_HAMILTONIAN_PROBLEM_PORT,
114
+ ],
110
115
  )
111
116
 
112
117
 
@@ -187,20 +192,33 @@ MOLECULE_RESULT = StructDeclaration(
187
192
 
188
193
  MOLECULE_PROBLEM_TO_HAMILTONIAN = ClassicalFunctionDeclaration(
189
194
  name="molecule_problem_to_hamiltonian",
190
- param_decls={"problem": Struct(name="MoleculeProblem")},
195
+ positional_parameters=[
196
+ ClassicalParameterDeclaration(
197
+ name="problem", classical_type=Struct(name="MoleculeProblem")
198
+ ),
199
+ ],
191
200
  return_type=ClassicalList(element_type=Struct(name="PauliTerm")),
192
201
  )
193
202
 
194
203
  FOCK_HAMILTONIAN_PROBLEM_TO_HAMILTONIAN = ClassicalFunctionDeclaration(
195
204
  name="fock_hamiltonian_problem_to_hamiltonian",
196
- param_decls={"problem": Struct(name="FockHamiltonianProblem")},
205
+ positional_parameters=[
206
+ ClassicalParameterDeclaration(
207
+ name="problem", classical_type=Struct(name="FockHamiltonianProblem")
208
+ ),
209
+ ],
197
210
  return_type=ClassicalList(element_type=Struct(name="PauliTerm")),
198
211
  )
199
212
 
200
213
 
201
214
  MOLECULE_GROUND_STATE_SOLUTION_POST_PROCESS = ClassicalFunctionDeclaration(
202
215
  name="molecule_ground_state_solution_post_process",
203
- param_decls={"problem": Struct(name="MoleculeProblem"), "vqe_result": VQEResult()},
216
+ positional_parameters=[
217
+ ClassicalParameterDeclaration(
218
+ name="problem", classical_type=Struct(name="MoleculeProblem")
219
+ ),
220
+ ClassicalParameterDeclaration(name="vqe_result", classical_type=VQEResult()),
221
+ ],
204
222
  return_type=Struct(name="MoleculeResult"),
205
223
  )
206
224
 
@@ -5,11 +5,14 @@ from classiq.interface.generator.functions.classical_type import (
5
5
  ClassicalList,
6
6
  Integer,
7
7
  Real,
8
- Struct,
9
8
  StructMetaType,
10
9
  VQEResult,
11
10
  )
11
+ from classiq.interface.generator.functions.type_name import Struct
12
12
  from classiq.interface.generator.types.struct_declaration import StructDeclaration
13
+ from classiq.interface.model.classical_parameter_declaration import (
14
+ ClassicalParameterDeclaration,
15
+ )
13
16
 
14
17
  COMBINATORIAL_OPTIMIZATION_SOLUTION = StructDeclaration(
15
18
  name="CombinatorialOptimizationSolution",
@@ -23,20 +26,26 @@ COMBINATORIAL_OPTIMIZATION_SOLUTION = StructDeclaration(
23
26
 
24
27
  OPTIMIZATION_PROBLEM_TO_HAMILTONIAN = ClassicalFunctionDeclaration(
25
28
  name="optimization_problem_to_hamiltonian",
26
- param_decls={
27
- "problem_type": StructMetaType(),
28
- "penalty_energy": Real(),
29
- },
29
+ positional_parameters=[
30
+ ClassicalParameterDeclaration(
31
+ name="problem_type", classical_type=StructMetaType()
32
+ ),
33
+ ClassicalParameterDeclaration(name="penalty_energy", classical_type=Real()),
34
+ ],
30
35
  return_type=ClassicalList(element_type=Struct(name="PauliTerm")),
31
36
  )
32
37
 
33
38
  GET_OPTIMIZATION_SOLUTION = ClassicalFunctionDeclaration(
34
39
  name="get_optimization_solution",
35
- param_decls={
36
- "problem_type": StructMetaType(),
37
- "vqe_result_handle": VQEResult(),
38
- "penalty_energy": Real(),
39
- },
40
+ positional_parameters=[
41
+ ClassicalParameterDeclaration(
42
+ name="problem_type", classical_type=StructMetaType()
43
+ ),
44
+ ClassicalParameterDeclaration(
45
+ name="vqe_result_handle", classical_type=VQEResult()
46
+ ),
47
+ ClassicalParameterDeclaration(name="penalty_energy", classical_type=Real()),
48
+ ],
40
49
  return_type=ClassicalList(
41
50
  element_type=Struct(name="CombinatorialOptimizationSolution")
42
51
  ),
@@ -6,19 +6,24 @@ from classiq.interface.generator.functions.classical_type import (
6
6
  ClassicalList,
7
7
  Integer,
8
8
  )
9
+ from classiq.interface.model.classical_parameter_declaration import (
10
+ ClassicalParameterDeclaration,
11
+ )
9
12
 
10
13
  GRID_ENTANGLER_GRAPH = ClassicalFunctionDeclaration(
11
14
  name="grid_entangler_graph",
12
- param_decls={
13
- "num_qubits": Integer(),
14
- "schmidt_rank": Integer(),
15
- "grid_randomization": Bool(),
16
- },
15
+ positional_parameters=[
16
+ ClassicalParameterDeclaration(name="num_qubits", classical_type=Integer()),
17
+ ClassicalParameterDeclaration(name="schmidt_rank", classical_type=Integer()),
18
+ ClassicalParameterDeclaration(name="grid_randomization", classical_type=Bool()),
19
+ ],
17
20
  return_type=ClassicalList(element_type=ClassicalList(element_type=Integer())),
18
21
  )
19
22
 
20
23
  HYPERCUBE_ENTANGLER_GRAPH = ClassicalFunctionDeclaration(
21
24
  name="hypercube_entangler_graph",
22
- param_decls={"num_qubits": Integer()},
25
+ positional_parameters=[
26
+ ClassicalParameterDeclaration(name="num_qubits", classical_type=Integer()),
27
+ ],
23
28
  return_type=ClassicalList(element_type=ClassicalList(element_type=Integer())),
24
29
  )
@@ -10,15 +10,18 @@ from classiq.interface.generator.functions.classical_type import (
10
10
  ClassicalList,
11
11
  Integer,
12
12
  Real,
13
- Struct,
14
13
  )
15
14
  from classiq.interface.generator.functions.port_declaration import (
16
15
  PortDeclarationDirection,
17
16
  )
17
+ from classiq.interface.generator.functions.type_name import Struct
18
18
  from classiq.interface.generator.types.struct_declaration import StructDeclaration
19
+ from classiq.interface.model.classical_parameter_declaration import (
20
+ ClassicalParameterDeclaration,
21
+ )
19
22
  from classiq.interface.model.port_declaration import PortDeclaration
20
23
  from classiq.interface.model.quantum_function_declaration import (
21
- QuantumFunctionDeclaration,
24
+ NamedParamsQuantumFunctionDeclaration,
22
25
  )
23
26
 
24
27
  if TYPE_CHECKING:
@@ -59,25 +62,28 @@ FINANCE_FUNCTION_PORT_SIZE_FUNCTION_MAPPING: Mapping[FinanceModelType, Callable]
59
62
 
60
63
  def _generate_finance_function(
61
64
  finance_model: FinanceModelType,
62
- ) -> QuantumFunctionDeclaration:
63
- return QuantumFunctionDeclaration(
65
+ ) -> NamedParamsQuantumFunctionDeclaration:
66
+ return NamedParamsQuantumFunctionDeclaration(
64
67
  name=f"{finance_model.value}_finance",
65
- param_decls={
66
- "finance_model": Struct(name=f"{finance_model.name}Model"),
67
- "finance_function": Struct(name="FinanceFunction"),
68
- },
69
- port_declarations={
70
- FUNCTION_PORT_NAME: PortDeclaration(
68
+ positional_arg_declarations=[
69
+ ClassicalParameterDeclaration(
70
+ name="finance_model",
71
+ classical_type=Struct(name=f"{finance_model.name}Model"),
72
+ ),
73
+ ClassicalParameterDeclaration(
74
+ name="finance_function", classical_type=Struct(name="FinanceFunction")
75
+ ),
76
+ PortDeclaration(
71
77
  name=FUNCTION_PORT_NAME,
72
78
  direction=PortDeclarationDirection.Inout,
73
79
  size=Expression(expr=FINANCE_FUNCTION_PORT_SIZE_MAPPING[finance_model]),
74
80
  ),
75
- OBJECTIVE_PORT_NAME: PortDeclaration(
81
+ PortDeclaration(
76
82
  name=OBJECTIVE_PORT_NAME,
77
83
  direction=PortDeclarationDirection.Inout,
78
84
  size=Expression(expr="1"),
79
85
  ),
80
- },
86
+ ],
81
87
  )
82
88
 
83
89
 
@@ -118,21 +124,29 @@ FINANCE_FUNCTION = StructDeclaration(
118
124
 
119
125
  LOG_NORMAL_FINANCE_POST_PROCESS = ClassicalFunctionDeclaration(
120
126
  name="log_normal_finance_post_process",
121
- param_decls={
122
- "finance_model": Struct(name="LogNormalModel"),
123
- "estimation_method": Struct(name="FinanceFunction"),
124
- "probability": Real(),
125
- },
127
+ positional_parameters=[
128
+ ClassicalParameterDeclaration(
129
+ name="finance_model", classical_type=Struct(name="LogNormalModel")
130
+ ),
131
+ ClassicalParameterDeclaration(
132
+ name="estimation_method", classical_type=Struct(name="FinanceFunction")
133
+ ),
134
+ ClassicalParameterDeclaration(name="probability", classical_type=Real()),
135
+ ],
126
136
  return_type=Real(),
127
137
  )
128
138
 
129
139
  GAUSSIAN_FINANCE_POST_PROCESS = ClassicalFunctionDeclaration(
130
140
  name="gaussian_finance_post_process",
131
- param_decls={
132
- "finance_model": Struct(name="GaussianModel"),
133
- "estimation_method": Struct(name="FinanceFunction"),
134
- "probability": Real(),
135
- },
141
+ positional_parameters=[
142
+ ClassicalParameterDeclaration(
143
+ name="finance_model", classical_type=Struct(name="GaussianModel")
144
+ ),
145
+ ClassicalParameterDeclaration(
146
+ name="estimation_method", classical_type=Struct(name="FinanceFunction")
147
+ ),
148
+ ClassicalParameterDeclaration(name="probability", classical_type=Real()),
149
+ ],
136
150
  return_type=Real(),
137
151
  )
138
152
 
@@ -3,18 +3,20 @@ import enum
3
3
  from classiq.interface.generator.expressions.expression import Expression
4
4
  from classiq.interface.generator.functions.classical_type import (
5
5
  ClassicalList,
6
- Enum,
7
6
  Integer,
8
7
  Real,
9
- Struct,
10
8
  )
11
9
  from classiq.interface.generator.functions.port_declaration import (
12
10
  PortDeclarationDirection,
13
11
  )
12
+ from classiq.interface.generator.functions.type_name import Enum, Struct
14
13
  from classiq.interface.generator.types.struct_declaration import StructDeclaration
14
+ from classiq.interface.model.classical_parameter_declaration import (
15
+ ClassicalParameterDeclaration,
16
+ )
15
17
  from classiq.interface.model.port_declaration import PortDeclaration
16
18
  from classiq.interface.model.quantum_function_declaration import (
17
- QuantumFunctionDeclaration,
19
+ NamedParamsQuantumFunctionDeclaration,
18
20
  )
19
21
 
20
22
 
@@ -24,29 +26,33 @@ class FeatureMapType(enum.Enum):
24
26
 
25
27
 
26
28
  QSVM_PAULI_FEATURE_MAP_SIZE = "get_field(feature_map, 'feature_dimension')"
27
- QSVM_PAULI_FEATURE_MAP = QuantumFunctionDeclaration(
29
+ QSVM_PAULI_FEATURE_MAP = NamedParamsQuantumFunctionDeclaration(
28
30
  name="pauli_feature_map",
29
- param_decls={"feature_map": Struct(name="QSVMFeatureMapPauli")},
30
- port_declarations={
31
- "qbv": PortDeclaration(
31
+ positional_arg_declarations=[
32
+ ClassicalParameterDeclaration(
33
+ name="feature_map", classical_type=Struct(name="QSVMFeatureMapPauli")
34
+ ),
35
+ PortDeclaration(
32
36
  name="qbv",
33
37
  direction=PortDeclarationDirection.Inout,
34
38
  size=Expression(expr=QSVM_PAULI_FEATURE_MAP_SIZE),
35
- )
36
- },
39
+ ),
40
+ ],
37
41
  )
38
42
 
39
43
  QSVM_BLOCH_SPHERE_FEATURE_MAP_SIZE = "ceiling(feature_dimension/2)"
40
- QSVM_BLOCH_SPHERE_FEATURE_MAP = QuantumFunctionDeclaration(
44
+ QSVM_BLOCH_SPHERE_FEATURE_MAP = NamedParamsQuantumFunctionDeclaration(
41
45
  name="bloch_sphere_feature_map",
42
- param_decls={"feature_dimension": Integer()},
43
- port_declarations={
44
- "qbv": PortDeclaration(
46
+ positional_arg_declarations=[
47
+ ClassicalParameterDeclaration(
48
+ name="feature_dimension", classical_type=Integer()
49
+ ),
50
+ PortDeclaration(
45
51
  name="qbv",
46
52
  direction=PortDeclarationDirection.Inout,
47
53
  size=Expression(expr=QSVM_BLOCH_SPHERE_FEATURE_MAP_SIZE),
48
- )
49
- },
54
+ ),
55
+ ],
50
56
  )
51
57
 
52
58
  QSVM_FEATURE_MAP_PAULI = StructDeclaration(
@@ -88,7 +88,27 @@ class ArithmeticExpressionABC(abc.ABC, FunctionParams):
88
88
  cls._validate_ast_obj(ast_obj)
89
89
 
90
90
  graph = parse_expression(expression)
91
- cls._validate_expression_graph(graph, values)
91
+ try:
92
+ cls._validate_expression_graph(graph, values)
93
+ except ClassiqValueError as e:
94
+ # This flow was created specifically for inplace Boolean XOR operations like q1 ^ q2.
95
+ # We can't plug equality in previous stages due to SymPy restrictions.
96
+ # Note that we don't validate that the expression itself is Boolean (passing non-Boolean expressions
97
+ # as inplace is currently not supported, so it's a bug).
98
+ if not e.raw_message == "Expression does not support target assignment":
99
+ raise
100
+ ast_parsed_expression = ast.parse(expression)
101
+ ast_expr = ast_parsed_expression.body[0]
102
+ if (
103
+ not isinstance(ast_expr, ast.Expr)
104
+ or not isinstance(ast_expr.value, ast.BinOp)
105
+ or not isinstance(ast_expr.value.op, ast.BitXor)
106
+ ):
107
+ raise
108
+ expression = f"({expression}) == 1"
109
+ graph = parse_expression(expression)
110
+ cls._validate_expression_graph(graph, values)
111
+
92
112
  validate_arithmetic_result_type(
93
113
  graph=graph,
94
114
  definitions=definitions,