classiq 0.68.0__py3-none-any.whl → 0.69.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 (47) hide show
  1. classiq/_internals/api_wrapper.py +4 -8
  2. classiq/applications/combinatorial_optimization/combinatorial_problem.py +8 -11
  3. classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
  4. classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
  5. classiq/applications/qnn/torch_utils.py +1 -1
  6. classiq/execution/jobs.py +2 -5
  7. classiq/interface/_version.py +1 -1
  8. classiq/interface/backend/quantum_backend_providers.py +2 -3
  9. classiq/interface/chemistry/operator.py +11 -7
  10. classiq/interface/debug_info/back_ref_util.py +22 -0
  11. classiq/interface/debug_info/debug_info.py +11 -21
  12. classiq/interface/executor/optimizer_preferences.py +1 -0
  13. classiq/interface/generator/arith/arithmetic_param_getters.py +3 -3
  14. classiq/interface/generator/functions/classical_type.py +12 -1
  15. classiq/interface/generator/generated_circuit_data.py +63 -24
  16. classiq/interface/generator/types/builtin_enum_declarations.py +1 -0
  17. classiq/interface/generator/types/enum_declaration.py +12 -1
  18. classiq/interface/ide/visual_model.py +0 -2
  19. classiq/interface/model/quantum_statement.py +1 -1
  20. classiq/interface/server/routes.py +0 -6
  21. classiq/model_expansions/generative_functions.py +4 -3
  22. classiq/model_expansions/quantum_operations/call_emitter.py +0 -13
  23. classiq/model_expansions/scope_initialization.py +5 -19
  24. classiq/open_library/functions/amplitude_amplification.py +3 -7
  25. classiq/open_library/functions/discrete_sine_cosine_transform.py +4 -4
  26. classiq/open_library/functions/grover.py +2 -2
  27. classiq/open_library/functions/hea.py +3 -3
  28. classiq/open_library/functions/modular_exponentiation.py +10 -20
  29. classiq/open_library/functions/qft_functions.py +2 -2
  30. classiq/open_library/functions/qsvt.py +8 -8
  31. classiq/open_library/functions/utility_functions.py +2 -2
  32. classiq/qmod/builtins/classical_functions.py +24 -7
  33. classiq/qmod/builtins/enums.py +1 -0
  34. classiq/qmod/builtins/functions/__init__.py +2 -0
  35. classiq/qmod/builtins/functions/exponentiation.py +24 -0
  36. classiq/qmod/builtins/operations.py +26 -11
  37. classiq/qmod/cparam.py +32 -5
  38. classiq/qmod/python_classical_type.py +10 -4
  39. classiq/qmod/quantum_callable.py +2 -1
  40. classiq/qmod/quantum_function.py +3 -2
  41. classiq/qmod/semantics/error_manager.py +1 -1
  42. classiq/qmod/utilities.py +29 -1
  43. classiq/synthesis.py +9 -6
  44. {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/METADATA +1 -1
  45. {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/RECORD +46 -46
  46. classiq/interface/execution/jobs.py +0 -31
  47. {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/WHEEL +0 -0
@@ -22,10 +22,6 @@ from classiq.interface.execution.iqcc import (
22
22
  IQCCProbeAuthData,
23
23
  IQCCProbeAuthResponse,
24
24
  )
25
- from classiq.interface.execution.jobs import (
26
- ExecutionJobDetailsV1,
27
- ExecutionJobsQueryResultsV1,
28
- )
29
25
  from classiq.interface.execution.primitives import PrimitivesInput
30
26
  from classiq.interface.executor import execution_request
31
27
  from classiq.interface.generator import quantum_program as generator_result
@@ -218,7 +214,7 @@ class ApiWrapper:
218
214
  job_id: JobID,
219
215
  name: str,
220
216
  http_client: Optional[httpx.AsyncClient] = None,
221
- ) -> ExecutionJobDetailsV1:
217
+ ) -> execution_request.ExecutionJobDetails:
222
218
  data = await cls._call_task(
223
219
  http_method=HTTPMethod.PATCH,
224
220
  url=f"{routes.EXECUTION_JOBS_FULL_PATH}/{job_id.job_id}",
@@ -227,7 +223,7 @@ class ApiWrapper:
227
223
  },
228
224
  http_client=http_client,
229
225
  )
230
- return ExecutionJobDetailsV1.model_validate(data)
226
+ return execution_request.ExecutionJobDetails.model_validate(data)
231
227
 
232
228
  @classmethod
233
229
  async def call_cancel_execution_job(
@@ -248,7 +244,7 @@ class ApiWrapper:
248
244
  offset: int,
249
245
  limit: int,
250
246
  http_client: Optional[httpx.AsyncClient] = None,
251
- ) -> ExecutionJobsQueryResultsV1:
247
+ ) -> execution_request.ExecutionJobsQueryResults:
252
248
  data = await cls._call_task(
253
249
  http_method=HTTPMethod.GET,
254
250
  url=f"{routes.EXECUTION_JOBS_FULL_PATH}",
@@ -258,7 +254,7 @@ class ApiWrapper:
258
254
  },
259
255
  http_client=http_client,
260
256
  )
261
- return ExecutionJobsQueryResultsV1.model_validate(data)
257
+ return execution_request.ExecutionJobsQueryResults.model_validate(data)
262
258
 
263
259
  @classmethod
264
260
  async def call_analysis_task(
@@ -24,7 +24,6 @@ from classiq.open_library.functions.utility_functions import (
24
24
  from classiq.qmod.builtins.functions import RX
25
25
  from classiq.qmod.builtins.operations import allocate, phase, repeat
26
26
  from classiq.qmod.cparam import CReal
27
- from classiq.qmod.create_model_function import create_model
28
27
  from classiq.qmod.qfunc import qfunc
29
28
  from classiq.qmod.qmod_parameter import CArray
30
29
  from classiq.qmod.qmod_variable import Output, QVar
@@ -75,17 +74,15 @@ class CombinatorialProblem:
75
74
  hadamard_transform(v)
76
75
  repeat(
77
76
  self.num_layers_,
78
- lambda i: [ # type:ignore[arg-type]
79
- phase(
80
- -self.cost_func(v), params[i]
81
- ), # type:ignore[func-returns-value]
77
+ lambda i: [
78
+ phase(-self.cost_func(v), params[i]),
82
79
  apply_to_all(lambda q: RX(params[self.num_layers_ + i], q), v),
83
80
  ],
84
81
  )
85
82
 
86
- self.model_ = create_model(
87
- main, constraints=constraints, preferences=preferences
88
- ) # type:ignore[assignment]
83
+ self.model_ = main.create_model(
84
+ constraints=constraints, preferences=preferences
85
+ ).get_model() # type:ignore[assignment]
89
86
  return self.model_ # type:ignore[return-value]
90
87
 
91
88
  def get_qprog(self) -> SerializedQuantumProgram:
@@ -199,13 +196,13 @@ def execute_qaoa(
199
196
  hadamard_transform(v)
200
197
  repeat(
201
198
  num_layers,
202
- lambda i: [ # type:ignore[arg-type]
203
- phase(-cost_func(v), params[i]), # type:ignore[func-returns-value]
199
+ lambda i: [
200
+ phase(-cost_func(v), params[i]),
204
201
  apply_to_all(lambda q: RX(params[num_layers + i], q), v),
205
202
  ],
206
203
  )
207
204
 
208
- model = create_model(main)
205
+ model = main.create_model().get_model()
209
206
  qprog = synthesize(model)
210
207
 
211
208
  with ExecutionSession(qprog, execution_preferences) as es:
@@ -18,7 +18,7 @@ class QuantumGradient(abc.ABC):
18
18
  execute: ExecuteFunction,
19
19
  post_process: PostProcessFunction,
20
20
  *args: Any,
21
- **kwargs: Any
21
+ **kwargs: Any,
22
22
  ) -> None:
23
23
  self._execute = execute
24
24
  self._post_process = post_process
@@ -71,7 +71,7 @@ class SimpleQuantumGradient(QuantumGradient):
71
71
  post_process: PostProcessFunction,
72
72
  epsilon: float = EPSILON,
73
73
  *args: Any,
74
- **kwargs: Any
74
+ **kwargs: Any,
75
75
  ) -> None:
76
76
  super().__init__(quantum_program, execute, post_process)
77
77
  self._epsilon = epsilon
@@ -94,7 +94,7 @@ def iter_inputs_weights(
94
94
  post_process: PostProcessFunction,
95
95
  *,
96
96
  expected_shape: Shape = (),
97
- requires_grad: Optional[bool] = None
97
+ requires_grad: Optional[bool] = None,
98
98
  ) -> Tensor:
99
99
  if is_single_layer_circuit(weights):
100
100
  iter_weights = torch.reshape(weights, (1, weights.shape[0]))
classiq/execution/jobs.py CHANGED
@@ -9,7 +9,6 @@ from classiq.interface.exceptions import (
9
9
  ClassiqAPIError,
10
10
  ClassiqError,
11
11
  )
12
- from classiq.interface.execution.jobs import ExecutionJobDetailsV1
13
12
  from classiq.interface.executor.execution_request import ExecutionJobDetails, JobCost
14
13
  from classiq.interface.executor.execution_result import ResultsCollection
15
14
  from classiq.interface.executor.result import (
@@ -26,8 +25,6 @@ from classiq._internals.async_utils import syncify_function
26
25
  from classiq._internals.client import client
27
26
  from classiq._internals.jobs import JobID, JobPoller
28
27
 
29
- _JobDetails = Union[ExecutionJobDetails, ExecutionJobDetailsV1]
30
-
31
28
 
32
29
  class ClassiqExecutionResultError(ClassiqError):
33
30
  def __init__(self, primitive: str) -> None:
@@ -37,10 +34,10 @@ class ClassiqExecutionResultError(ClassiqError):
37
34
 
38
35
 
39
36
  class ExecutionJob:
40
- _details: _JobDetails
37
+ _details: ExecutionJobDetails
41
38
  _result: Optional[ResultsCollection]
42
39
 
43
- def __init__(self, details: _JobDetails) -> None:
40
+ def __init__(self, details: ExecutionJobDetails) -> None:
44
41
  self._details = details
45
42
  self._result = None
46
43
 
@@ -3,5 +3,5 @@ from packaging.version import Version
3
3
  # This file was generated automatically
4
4
  # Please don't track in version control (DONTTRACK)
5
5
 
6
- SEMVER_VERSION = '0.68.0'
6
+ SEMVER_VERSION = '0.69.0'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -172,15 +172,14 @@ class ClassiqNvidiaBackendNames(StrEnum):
172
172
 
173
173
  SIMULATOR = "nvidia_simulator"
174
174
  SIMULATOR_STATEVECTOR = "nvidia_simulator_statevector"
175
+ BRAKET_NVIDIA_SIMULATOR = "braket_nvidia_simulator"
176
+ BRAKET_NVIDIA_SIMULATOR_STATEVECTOR = "braket_nvidia_simulator_statevector"
175
177
 
176
178
 
177
179
  class IntelBackendNames(StrEnum):
178
180
  SIMULATOR = "intel_qsdk_simulator"
179
181
 
180
182
 
181
- AllClassiqBackendNames = Union[ClassiqSimulatorBackendNames, ClassiqNvidiaBackendNames]
182
-
183
-
184
183
  class GoogleNvidiaBackendNames(StrEnum):
185
184
  """
186
185
  Google backend names which Classiq Supports running on.
@@ -1,5 +1,6 @@
1
1
  from collections.abc import Collection
2
2
  from functools import reduce
3
+ from itertools import combinations
3
4
  from typing import (
4
5
  Any,
5
6
  Optional,
@@ -144,16 +145,19 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
144
145
  @property
145
146
  def is_commutative(self) -> bool:
146
147
  return all(
147
- self._is_sub_pauli_commutative(
148
- [summand[0][qubit_num] for summand in self.pauli_list]
149
- )
150
- for qubit_num in range(self.num_qubits)
148
+ self._do_paulis_commute(first[0], second[0])
149
+ for first, second in combinations(self.pauli_list, 2)
151
150
  )
152
151
 
153
152
  @staticmethod
154
- def _is_sub_pauli_commutative(qubit_pauli_string: Union[list[str], str]) -> bool:
155
- unique_paulis = set(qubit_pauli_string) - {"I"}
156
- return len(unique_paulis) <= 1
153
+ def _do_paulis_commute(
154
+ first: PydanticPauliMonomialStr, second: PydanticPauliMonomialStr
155
+ ) -> bool:
156
+ commute = True
157
+ for c1, c2 in zip(first, second):
158
+ if (c1 != "I") and (c2 != "I") and (c1 != c2):
159
+ commute = not commute
160
+ return commute
157
161
 
158
162
  @property
159
163
  def num_qubits(self) -> int:
@@ -0,0 +1,22 @@
1
+ from classiq.interface.model.allocate import Allocate
2
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
3
+ from classiq.interface.model.statement_block import (
4
+ ConcreteQuantumStatement,
5
+ StatementBlock,
6
+ )
7
+
8
+ """
9
+ This module contains helper functions to determine if a given quantum statement
10
+ is an allocation or free statement.
11
+ """
12
+
13
+
14
+ def is_allocate_or_free(concrete_quantum_statement: ConcreteQuantumStatement) -> bool:
15
+ return isinstance(concrete_quantum_statement, Allocate) or (
16
+ isinstance(concrete_quantum_statement, QuantumFunctionCall)
17
+ and concrete_quantum_statement.function == "free"
18
+ )
19
+
20
+
21
+ def is_allocate_or_free_by_backref(back_refs: StatementBlock) -> bool:
22
+ return len(back_refs) > 0 and is_allocate_or_free(back_refs[0])
@@ -1,34 +1,23 @@
1
- import json
2
1
  from collections.abc import Mapping
3
- from typing import Any, Optional, Union
2
+ from typing import Optional, Union
4
3
  from uuid import UUID
5
4
 
6
5
  from pydantic import BaseModel, Field
7
6
 
8
- from classiq.interface.enum_utils import StrEnum
7
+ from classiq.interface.debug_info import back_ref_util
9
8
  from classiq.interface.generator.generated_circuit_data import (
10
9
  FunctionDebugInfoInterface,
11
10
  OperationLevel,
11
+ StatementType,
12
12
  )
13
13
  from classiq.interface.model.statement_block import ConcreteQuantumStatement
14
14
 
15
15
  ParameterValue = Union[float, int, str, None]
16
16
 
17
17
 
18
- class StatementType(StrEnum):
19
- CONTROL = "control"
20
- POWER = "power"
21
- INVERT = "invert"
22
- WITHIN_APPLY = "within_apply"
23
- ASSIGNMENT = "assignment"
24
- REPEAT = "repeat"
25
-
26
-
27
18
  class FunctionDebugInfo(BaseModel):
28
19
  name: str
29
- # Parameters describe classical parameters passed to function
30
- parameters: dict[str, str]
31
- level: OperationLevel
20
+ level: OperationLevel = Field(default=OperationLevel.UNKNOWN)
32
21
  statement_type: Union[StatementType, None] = None
33
22
  is_allocate_or_free: bool = Field(default=False)
34
23
  is_inverse: bool = Field(default=False)
@@ -36,12 +25,13 @@ class FunctionDebugInfo(BaseModel):
36
25
  port_to_passed_variable_map: dict[str, str] = Field(default_factory=dict)
37
26
  node: Optional[ConcreteQuantumStatement] = None
38
27
 
39
- @staticmethod
40
- def param_controller(value: Any) -> str:
41
- try:
42
- return json.dumps(value)
43
- except TypeError:
44
- return repr(value)
28
+ @property
29
+ def is_allocate_or_free_(self) -> bool:
30
+ return (
31
+ back_ref_util.is_allocate_or_free(self.node)
32
+ if self.node is not None
33
+ else self.is_allocate_or_free
34
+ )
45
35
 
46
36
  def update_map_from_port_mapping(self, port_mapping: Mapping[str, str]) -> None:
47
37
  new_port_to_passed_variable_map = self.port_to_passed_variable_map.copy()
@@ -21,6 +21,7 @@ class OptimizerType(StrEnum):
21
21
  L_BFGS_B = "L_BFGS_B"
22
22
  NELDER_MEAD = "NELDER_MEAD"
23
23
  ADAM = "ADAM"
24
+ SLSQP = "SLSQP"
24
25
 
25
26
 
26
27
  class OptimizerPreferences(BaseModel):
@@ -59,7 +59,7 @@ def get_params(
59
59
  machine_precision: int,
60
60
  output_size: Optional[int] = None,
61
61
  inplace_arg: Optional[str] = None,
62
- target: Optional[RegisterArithmeticInfo] = None
62
+ target: Optional[RegisterArithmeticInfo] = None,
63
63
  ) -> ArithmeticOperationParams:
64
64
  operation = id2op(node_id)
65
65
  if target and not operation_allows_target(operation):
@@ -334,7 +334,7 @@ def logical_and_params_getter(
334
334
  machine_precision: int,
335
335
  output_size: Optional[int] = None,
336
336
  inplace_arg: Optional[str] = None,
337
- target: Optional[RegisterArithmeticInfo] = None
337
+ target: Optional[RegisterArithmeticInfo] = None,
338
338
  ) -> ArithmeticOperationParams:
339
339
  return LogicalAnd(args=arg, target=target, machine_precision=machine_precision)
340
340
 
@@ -344,7 +344,7 @@ def logical_or_params_getter(
344
344
  machine_precision: int,
345
345
  output_size: Optional[int] = None,
346
346
  inplace_arg: Optional[str] = None,
347
- target: Optional[RegisterArithmeticInfo] = None
347
+ target: Optional[RegisterArithmeticInfo] = None,
348
348
  ) -> ArithmeticOperationParams:
349
349
  return LogicalOr(args=arg, target=target, machine_precision=machine_precision)
350
350
 
@@ -1,8 +1,9 @@
1
1
  from typing import TYPE_CHECKING, Any, Literal, Union
2
2
 
3
3
  import pydantic
4
- from pydantic import ConfigDict
4
+ from pydantic import ConfigDict, PrivateAttr
5
5
  from sympy import IndexedBase, Symbol
6
+ from typing_extensions import Self
6
7
 
7
8
  from classiq.interface.ast_node import HashableASTNode
8
9
  from classiq.interface.generator.expressions.expression_types import RuntimeExpression
@@ -19,6 +20,8 @@ NamedSymbol = Union[IndexedBase, Symbol]
19
20
 
20
21
 
21
22
  class ClassicalType(HashableASTNode):
23
+ _is_generative: bool = PrivateAttr(default=False)
24
+
22
25
  def as_symbolic(self, name: str) -> Union[NamedSymbol, list[NamedSymbol]]:
23
26
  return Symbol(name)
24
27
 
@@ -27,6 +30,14 @@ class ClassicalType(HashableASTNode):
27
30
  def __str__(self) -> str:
28
31
  return str(type(self).__name__)
29
32
 
33
+ def set_generative(self) -> Self:
34
+ self._is_generative = True
35
+ return self
36
+
37
+ @property
38
+ def is_generative(self) -> bool:
39
+ return self._is_generative
40
+
30
41
 
31
42
  class Integer(ClassicalType):
32
43
  kind: Literal["int"]
@@ -2,16 +2,24 @@ import logging
2
2
  from typing import Literal, Optional, Union
3
3
 
4
4
  import pydantic
5
- from pydantic import ConfigDict
5
+ from pydantic import ConfigDict, Field
6
6
  from typing_extensions import TypeAlias
7
7
 
8
+ from classiq.interface.debug_info.back_ref_util import is_allocate_or_free_by_backref
8
9
  from classiq.interface.enum_utils import StrEnum
9
10
  from classiq.interface.generator.control_state import ControlState
10
11
  from classiq.interface.generator.register_role import RegisterRole
11
12
  from classiq.interface.generator.synthesis_metadata.synthesis_execution_data import (
12
13
  ExecutionData,
13
14
  )
14
- from classiq.interface.model.statement_block import StatementBlock
15
+ from classiq.interface.model.quantum_expressions.quantum_expression import (
16
+ QuantumExpressionOperation,
17
+ )
18
+ from classiq.interface.model.statement_block import (
19
+ ConcreteQuantumStatement,
20
+ QuantumFunctionCall,
21
+ StatementBlock,
22
+ )
15
23
 
16
24
  from classiq.model_expansions.capturing.mangling_utils import (
17
25
  demangle_capture_name,
@@ -120,35 +128,75 @@ class OperationLevel(StrEnum):
120
128
  UNKNOWN = "UNKNOWN"
121
129
 
122
130
 
123
- class OperationParameter(pydantic.BaseModel):
124
- label: str
125
- value: Optional[str] = None
131
+ class StatementType(StrEnum):
132
+ CONTROL = "control"
133
+ POWER = "power"
134
+ INVERT = "invert"
135
+ WITHIN_APPLY = "within_apply"
136
+ ASSIGNMENT = "assignment"
137
+ REPEAT = "repeat"
126
138
 
127
139
 
128
140
  class FunctionDebugInfoInterface(pydantic.BaseModel):
129
- generated_function: Optional[GeneratedFunction] = pydantic.Field(default=None)
141
+ generated_function: Optional[GeneratedFunction] = Field(default=None)
130
142
  children: list["FunctionDebugInfoInterface"]
131
143
  relative_qubits: tuple[int, ...]
132
- absolute_qubits: Optional[tuple[int, ...]] = pydantic.Field(default=None)
133
- is_basis_gate: Optional[bool] = pydantic.Field(default=None)
134
- is_inverse: bool = pydantic.Field(default=False)
135
- is_allocate_or_free: bool = pydantic.Field(default=False)
136
- level: OperationLevel = pydantic.Field(default=OperationLevel.UNKNOWN)
137
- parameters: list[OperationParameter] = list()
138
- port_to_passed_variable_map: dict[str, str] = pydantic.Field(default={})
139
- release_by_inverse: bool = pydantic.Field(default=False)
140
- back_refs: StatementBlock = pydantic.Field(default_factory=list)
144
+ absolute_qubits: Optional[tuple[int, ...]] = Field(default=None)
145
+ is_basis_gate: Optional[bool] = Field(default=None)
146
+ is_inverse: bool = Field(default=False)
147
+ is_allocate_or_free: bool = Field(default=False)
148
+ level: OperationLevel = Field(default=OperationLevel.UNKNOWN)
149
+ port_to_passed_variable_map: dict[str, str] = Field(default={})
150
+ release_by_inverse: bool = Field(default=False)
151
+ back_refs: StatementBlock = Field(default_factory=list)
141
152
 
142
153
  model_config = ConfigDict(extra="allow")
143
154
  # Temporary field to store the override debug info for parallel old/new visualization
144
155
  override_debug_info: Optional["FunctionDebugInfoInterface"] = None
145
156
 
157
+ @property
158
+ def is_allocate_or_free_(self) -> bool:
159
+ """
160
+ temporary measure to handle the fact that in the current release we do not have
161
+ the backref, and therefore fallback to the old field of is_allocate_or_free
162
+ """
163
+ return (
164
+ is_allocate_or_free_by_backref(self.back_refs)
165
+ if bool(self.back_refs)
166
+ else self.is_allocate_or_free
167
+ )
168
+
146
169
  @property
147
170
  def name(self) -> str:
148
171
  if self.generated_function is None:
149
172
  return ""
150
173
  return self.generated_function.name
151
174
 
175
+ @property
176
+ def first_back_ref(self) -> Optional[ConcreteQuantumStatement]:
177
+ return self.back_refs[0] if self.back_refs else None
178
+
179
+ @property
180
+ def level_(self) -> OperationLevel:
181
+ # Temp fix for currently "supported" statements
182
+ if self.name in {StatementType.CONTROL, StatementType.POWER}:
183
+ return OperationLevel.QMOD_STATEMENT
184
+
185
+ back_ref = self.first_back_ref
186
+ if back_ref is None:
187
+ # This is the expected behavior for the case where there's not back ref.
188
+ # We will use it once we can rely on the existence of the back ref in
189
+ # all expected cases (non-engine calls)
190
+ # return OperationLevel.ENGINE_FUNCTION_CALL
191
+ return self.level
192
+ if isinstance(back_ref, QuantumFunctionCall):
193
+ return OperationLevel.QMOD_FUNCTION_CALL
194
+ # Temp "fix" for assignment statements until we have a way to fully
195
+ # distinguish them and to properly display them
196
+ if isinstance(back_ref, QuantumExpressionOperation):
197
+ return OperationLevel.ENGINE_FUNCTION_CALL
198
+ return OperationLevel.QMOD_STATEMENT
199
+
152
200
  @property
153
201
  def registers(self) -> list[GeneratedRegister]:
154
202
  if self.generated_function is None:
@@ -167,15 +215,6 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
167
215
  return list()
168
216
  return self.generated_function.control_states
169
217
 
170
- @staticmethod
171
- def create_parameters_from_dict(
172
- parameters: dict[str, str],
173
- ) -> list[OperationParameter]:
174
- return [
175
- OperationParameter(label=key, value=value)
176
- for key, value in parameters.items()
177
- ]
178
-
179
218
  def propagate_absolute_qubits(self) -> "FunctionDebugInfoInterface":
180
219
  if self.absolute_qubits is None:
181
220
  return self
@@ -150,6 +150,7 @@ class Optimizer(IntEnum):
150
150
  L_BFGS_B = 3
151
151
  NELDER_MEAD = 4
152
152
  ADAM = 5
153
+ SLSQP = 6
153
154
 
154
155
 
155
156
  class Pauli(IntEnum):
@@ -75,7 +75,7 @@ class EnumDeclaration(HashableASTNode):
75
75
 
76
76
 
77
77
  def declaration_from_enum(enum_type: EnumMeta) -> EnumDeclaration:
78
- members: list[Enum] = list(enum_type)
78
+ members = _get_members(enum_type)
79
79
  return EnumDeclaration(
80
80
  name=enum_type.__name__,
81
81
  members={
@@ -83,3 +83,14 @@ def declaration_from_enum(enum_type: EnumMeta) -> EnumDeclaration:
83
83
  for member in sorted(members, key=lambda member: member.value)
84
84
  },
85
85
  )
86
+
87
+
88
+ def _get_members(enum_type: EnumMeta) -> list[Enum]:
89
+ members: list[Enum] = list(enum_type)
90
+ for member in members:
91
+ if not isinstance(member.value, int):
92
+ raise ClassiqValueError(
93
+ f"Member {member.name!r} of enum {enum_type.__name__!r} has a "
94
+ f"non-integer value {member.value!r}"
95
+ )
96
+ return members
@@ -7,7 +7,6 @@ from pydantic import ConfigDict
7
7
  from classiq.interface.enum_utils import StrEnum
8
8
  from classiq.interface.generator.generated_circuit_data import (
9
9
  OperationLevel,
10
- OperationParameter,
11
10
  )
12
11
  from classiq.interface.generator.hardware.hardware_data import SynthesisHardwareData
13
12
  from classiq.interface.helpers.versioned_model import VersionedModel
@@ -114,7 +113,6 @@ class Operation(pydantic.BaseModel):
114
113
  control_qubits: tuple[int, ...] = pydantic.Field(default_factory=tuple)
115
114
  auxiliary_qubits: tuple[int, ...]
116
115
  target_qubits: tuple[int, ...]
117
- parameters: list[OperationParameter] = pydantic.Field(default_factory=list)
118
116
  operation_level: OperationLevel
119
117
  operation_type: OperationType = pydantic.Field(
120
118
  description="Identifies unique operations that are visualized differently"
@@ -27,7 +27,7 @@ class QuantumStatement(ASTNode):
27
27
  *,
28
28
  update: Optional[dict[str, Any]] = None,
29
29
  deep: bool = False,
30
- keep_uuid: bool = False
30
+ keep_uuid: bool = False,
31
31
  ) -> Self:
32
32
  if not keep_uuid:
33
33
  update = update or dict()
@@ -7,9 +7,6 @@ PROVIDERS_PREFIX = "/providers"
7
7
 
8
8
  IQCC_PREFIX = PROVIDERS_PREFIX + "/iqcc"
9
9
 
10
- EXECUTION_NON_VERSIONED_PREFIX = "/execution/v1"
11
- SYNTHESIS_NON_VERSIONED_PREFIX = "/synthesis/v1"
12
-
13
10
  ANALYZER_CIRCUIT_PAGE = "circuit"
14
11
  DEFAULT_IDE_FE_APP = "https://platform.classiq.io/"
15
12
 
@@ -58,9 +55,6 @@ TASKS_GENERATE_FULL_PATH = TASKS_GENERATE_SUFFIX
58
55
 
59
56
  EXECUTION_JOBS_SUFFIX = "/jobs"
60
57
  EXECUTION_JOBS_FULL_PATH = EXECUTION_PREFIX + EXECUTION_JOBS_SUFFIX
61
- EXECUTION_JOBS_NON_VERSIONED_FULL_PATH = (
62
- EXECUTION_NON_VERSIONED_PREFIX + EXECUTION_JOBS_SUFFIX
63
- )
64
58
 
65
59
  ANALYZER_FULL_PATH = ANALYZER_PREFIX + TASKS_SUFFIX
66
60
  ANALYZER_RB_FULL_PATH = ANALYZER_PREFIX + TASK_RB_SUFFIX
@@ -148,7 +148,8 @@ def emit_generative_statements(
148
148
  with _InterpreterExpandable(interpreter):
149
149
  set_frontend_interpreter(interpreter)
150
150
  for block_name, generative_function in operation.generative_blocks.items():
151
- with interpreter._builder.block_context(
152
- block_name
153
- ), generative_mode_context(True):
151
+ with (
152
+ interpreter._builder.block_context(block_name),
153
+ generative_mode_context(True),
154
+ ):
154
155
  generative_function._py_callable(*python_qmod_args)
@@ -13,9 +13,6 @@ from classiq.interface.generator.functions.port_declaration import (
13
13
  PortDeclarationDirection,
14
14
  )
15
15
  from classiq.interface.generator.generated_circuit_data import OperationLevel
16
- from classiq.interface.model.classical_parameter_declaration import (
17
- ClassicalParameterDeclaration,
18
- )
19
16
  from classiq.interface.model.handle_binding import HandleBinding
20
17
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
21
18
  from classiq.interface.model.port_declaration import PortDeclaration
@@ -162,11 +159,6 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
162
159
  back_ref=self._get_back_ref(propagated_debug_info),
163
160
  )
164
161
  is_allocate_or_free = new_call.func_name == free.func_decl.name
165
- parameters = {
166
- arg_decl.name: FunctionDebugInfo.param_controller(value=evaluated_arg.value)
167
- for arg_decl, evaluated_arg in zip(new_positional_arg_decls, evaluated_args)
168
- if isinstance(arg_decl, ClassicalParameterDeclaration)
169
- }
170
162
 
171
163
  port_to_passed_variable_map = {
172
164
  arg_decl.name: str(evaluated_arg.value.handle)
@@ -176,11 +168,6 @@ class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSpl
176
168
  self._debug_info[new_call.uuid] = FunctionDebugInfo(
177
169
  name=new_call.func_name,
178
170
  level=OperationLevel.QMOD_FUNCTION_CALL,
179
- parameters=(
180
- parameters
181
- if propagated_debug_info is None or propagated_debug_info.name == ""
182
- else propagated_debug_info.parameters
183
- ),
184
171
  is_allocate_or_free=is_allocate_or_free,
185
172
  port_to_passed_variable_map=port_to_passed_variable_map,
186
173
  node=new_call._as_back_ref(),