classiq 0.65.4__py3-none-any.whl → 0.66.1__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 (62) hide show
  1. classiq/_internals/api_wrapper.py +43 -0
  2. classiq/applications/qnn/qlayer.py +65 -3
  3. classiq/execution/execution_session.py +0 -2
  4. classiq/execution/iqcc.py +66 -1
  5. classiq/interface/_version.py +1 -1
  6. classiq/interface/ast_node.py +15 -1
  7. classiq/interface/backend/backend_preferences.py +0 -14
  8. classiq/interface/debug_info/debug_info.py +2 -0
  9. classiq/interface/execution/iqcc.py +25 -0
  10. classiq/interface/generator/expressions/qmod_qarray_proxy.py +1 -13
  11. classiq/interface/generator/visitor.py +7 -4
  12. classiq/interface/model/classical_if.py +4 -0
  13. classiq/interface/model/control.py +4 -0
  14. classiq/interface/model/invert.py +4 -0
  15. classiq/interface/model/model.py +3 -1
  16. classiq/interface/model/model_visitor.py +14 -0
  17. classiq/interface/model/power.py +4 -0
  18. classiq/interface/model/quantum_statement.py +3 -3
  19. classiq/interface/model/repeat.py +4 -0
  20. classiq/interface/model/within_apply_operation.py +4 -0
  21. classiq/interface/server/routes.py +6 -0
  22. classiq/model_expansions/closure.py +0 -11
  23. classiq/model_expansions/evaluators/quantum_type_utils.py +6 -6
  24. classiq/model_expansions/expression_evaluator.py +10 -1
  25. classiq/model_expansions/interpreters/base_interpreter.py +28 -18
  26. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +58 -1
  27. classiq/model_expansions/interpreters/generative_interpreter.py +7 -13
  28. classiq/model_expansions/quantum_operations/allocate.py +69 -0
  29. classiq/model_expansions/quantum_operations/call_emitter.py +7 -6
  30. classiq/model_expansions/quantum_operations/declarative_call_emitter.py +4 -4
  31. classiq/model_expansions/quantum_operations/emitter.py +2 -15
  32. classiq/model_expansions/quantum_operations/quantum_function_call.py +22 -0
  33. classiq/model_expansions/quantum_operations/shallow_emitter.py +21 -35
  34. classiq/model_expansions/scope_initialization.py +49 -34
  35. classiq/model_expansions/transformers/model_renamer.py +98 -0
  36. classiq/model_expansions/transformers/var_splitter.py +7 -82
  37. classiq/open_library/functions/__init__.py +8 -0
  38. classiq/open_library/functions/amplitude_amplification.py +92 -0
  39. classiq/open_library/functions/grover.py +5 -5
  40. classiq/qmod/builtins/__init__.py +1 -1
  41. classiq/qmod/builtins/functions/__init__.py +0 -2
  42. classiq/qmod/builtins/functions/allocation.py +1 -26
  43. classiq/qmod/builtins/operations.py +12 -6
  44. classiq/qmod/generative.py +6 -4
  45. classiq/qmod/native/pretty_printer.py +3 -2
  46. classiq/qmod/pretty_print/pretty_printer.py +3 -1
  47. classiq/qmod/qmod_variable.py +6 -1
  48. classiq/qmod/semantics/annotation/call_annotation.py +30 -2
  49. classiq/qmod/semantics/annotation/qstruct_annotator.py +2 -2
  50. classiq/qmod/semantics/error_manager.py +20 -6
  51. classiq/qmod/semantics/static_semantics_visitor.py +3 -40
  52. classiq/qmod/semantics/validation/constants_validation.py +2 -3
  53. classiq/qmod/semantics/validation/function_name_collisions_validation.py +6 -9
  54. classiq/qmod/semantics/validation/main_validation.py +2 -3
  55. classiq/qmod/semantics/validation/model_validation.py +25 -0
  56. classiq/qmod/semantics/validation/signature_validation.py +24 -0
  57. classiq/qmod/semantics/validation/types_validation.py +45 -46
  58. classiq/qmod/utilities.py +12 -0
  59. {classiq-0.65.4.dist-info → classiq-0.66.1.dist-info}/METADATA +1 -1
  60. {classiq-0.65.4.dist-info → classiq-0.66.1.dist-info}/RECORD +61 -56
  61. classiq/model_expansions/expression_renamer.py +0 -76
  62. {classiq-0.65.4.dist-info → classiq-0.66.1.dist-info}/WHEEL +0 -0
@@ -13,8 +13,11 @@ from classiq.interface.chemistry import ground_state_problem, operator
13
13
  from classiq.interface.enum_utils import StrEnum
14
14
  from classiq.interface.exceptions import ClassiqAPIError, ClassiqValueError
15
15
  from classiq.interface.execution.iqcc import (
16
+ IQCCAuthItemsDetails,
16
17
  IQCCInitAuthData,
17
18
  IQCCInitAuthResponse,
19
+ IQCCListAuthMethods,
20
+ IQCCListAuthTargets,
18
21
  IQCCProbeAuthData,
19
22
  IQCCProbeAuthResponse,
20
23
  )
@@ -445,3 +448,43 @@ class ApiWrapper:
445
448
  raise
446
449
 
447
450
  return IQCCProbeAuthResponse.model_validate(response)
451
+
452
+ @classmethod
453
+ async def call_iqcc_list_auth_scopes(
454
+ cls,
455
+ http_client: Optional[httpx.AsyncClient] = None,
456
+ ) -> IQCCAuthItemsDetails:
457
+ response = await cls._call_task(
458
+ http_method=HTTPMethod.GET,
459
+ url=routes.IQCC_LIST_AUTH_SCOPES_FULL_PATH,
460
+ http_client=http_client,
461
+ )
462
+ return IQCCAuthItemsDetails.model_validate(response)
463
+
464
+ @classmethod
465
+ async def call_iqcc_list_auth_methods(
466
+ cls,
467
+ data: IQCCListAuthMethods,
468
+ http_client: Optional[httpx.AsyncClient] = None,
469
+ ) -> IQCCAuthItemsDetails:
470
+ response = await cls._call_task_pydantic(
471
+ http_method=HTTPMethod.PUT,
472
+ url=routes.IQCC_LIST_AUTH_METHODS_FULL_PATH,
473
+ model=data,
474
+ http_client=http_client,
475
+ )
476
+ return IQCCAuthItemsDetails.model_validate(response)
477
+
478
+ @classmethod
479
+ async def call_iqcc_list_auth_targets(
480
+ cls,
481
+ data: IQCCListAuthTargets,
482
+ http_client: Optional[httpx.AsyncClient] = None,
483
+ ) -> IQCCAuthItemsDetails:
484
+ response = await cls._call_task_pydantic(
485
+ http_method=HTTPMethod.PUT,
486
+ url=routes.IQCC_LIST_AUTH_TARGETS_FULL_PATH,
487
+ model=data,
488
+ http_client=http_client,
489
+ )
490
+ return IQCCAuthItemsDetails.model_validate(response)
@@ -1,12 +1,16 @@
1
1
  import functools
2
- from typing import Any, Callable, Optional, Union
2
+ import inspect
3
+ import typing
4
+ from typing import Any, Callable, Optional, Union, overload
3
5
 
6
+ import more_itertools
4
7
  import torch
5
8
  import torch.nn as nn
6
9
  from torch import Tensor
7
10
  from torch.nn.parameter import Parameter
8
11
 
9
12
  from classiq.interface.exceptions import ClassiqQNNError, ClassiqTorchError
13
+ from classiq.interface.executor.execution_result import ResultsCollection
10
14
 
11
15
  from classiq.applications.qnn.circuit_utils import (
12
16
  extract_parameters,
@@ -29,6 +33,8 @@ from classiq.applications.qnn.types import (
29
33
  MultipleArguments,
30
34
  PostProcessFunction,
31
35
  )
36
+ from classiq.execution import ExecutionSession
37
+ from classiq.execution.qnn import _MAX_ARGUMENTS_SIZE, _execute_qnn_sample
32
38
  from classiq.synthesis import SerializedQuantumProgram
33
39
 
34
40
 
@@ -146,6 +152,7 @@ def calc_num_out_features_single_output(
146
152
  # Todo: extend the input to allow for multiple `qcode` - one for each output
147
153
  # thus allowing (something X n) instead of (something X 1) output
148
154
  class QLayer(nn.Module):
155
+ @overload
149
156
  def __init__(
150
157
  self,
151
158
  quantum_program: SerializedQuantumProgram,
@@ -156,12 +163,56 @@ class QLayer(nn.Module):
156
163
  # Experimental parameters:
157
164
  calc_num_out_features: CalcNumOutFeatures = calc_num_out_features_single_output,
158
165
  epsilon: float = EPSILON,
166
+ ) -> None: ...
167
+
168
+ @overload
169
+ def __init__(
170
+ self,
171
+ quantum_program: SerializedQuantumProgram,
172
+ post_process: PostProcessFunction,
173
+ /,
174
+ # Optional parameters:
175
+ head_start: Union[float, Tensor, None] = None,
176
+ # Experimental parameters:
177
+ calc_num_out_features: CalcNumOutFeatures = calc_num_out_features_single_output,
178
+ epsilon: float = EPSILON,
179
+ ) -> None: ...
180
+
181
+ def __init__(
182
+ self,
183
+ quantum_program: SerializedQuantumProgram,
184
+ *args: Any,
185
+ **kwargs: Any,
159
186
  ) -> None:
160
187
  circuit = Circuit.model_validate_json(quantum_program)
161
188
  validate_circuit(circuit)
162
189
 
163
190
  super().__init__()
164
191
 
192
+ arg_list = list(args)
193
+
194
+ if "execute" in kwargs:
195
+ execute = kwargs.pop("execute")
196
+ typing.cast(ExecuteFunction, execute)
197
+ # Check if the next argument is the post-process function (which means the QLayer is constructed without an execute)
198
+ elif inspect.signature(arg_list[0]).return_annotation is Tensor:
199
+ execute = self._make_execute(quantum_program)
200
+ else:
201
+ execute = arg_list.pop(0)
202
+
203
+ self._initialize(quantum_program, circuit, execute, *arg_list, **kwargs)
204
+ self._initialize_parameters()
205
+
206
+ def _initialize(
207
+ self,
208
+ quantum_program: SerializedQuantumProgram,
209
+ circuit: Circuit,
210
+ execute: ExecuteFunction,
211
+ post_process: PostProcessFunction,
212
+ head_start: Union[float, Tensor, None] = None,
213
+ calc_num_out_features: CalcNumOutFeatures = calc_num_out_features_single_output,
214
+ epsilon: float = EPSILON,
215
+ ) -> None:
165
216
  self._execute = execute
166
217
  self._post_process = post_process
167
218
  self._head_start = head_start
@@ -173,8 +224,6 @@ class QLayer(nn.Module):
173
224
  self.in_features: int = len(weights)
174
225
  self.out_features: int = calc_num_out_features(quantum_program)
175
226
 
176
- self._initialize_parameters()
177
-
178
227
  def _initialize_parameters(self) -> None:
179
228
  shape: tuple[int, ...] = (
180
229
  (self.out_features, self.in_features)
@@ -195,6 +244,19 @@ class QLayer(nn.Module):
195
244
 
196
245
  self.weight = Parameter(value)
197
246
 
247
+ @staticmethod
248
+ def _make_execute(quantum_program: SerializedQuantumProgram) -> ExecuteFunction:
249
+ session = ExecutionSession(quantum_program)
250
+
251
+ def execute(_ignored: Any, arguments: MultipleArguments) -> ResultsCollection:
252
+ result: ResultsCollection = []
253
+ for chunk in more_itertools.chunked(arguments, _MAX_ARGUMENTS_SIZE):
254
+ chunk_result = _execute_qnn_sample(session, chunk)
255
+ result.extend(chunk_result)
256
+ return result
257
+
258
+ return execute
259
+
198
260
  def forward(self, x: Tensor) -> Tensor:
199
261
  return QLayerFunction.apply(
200
262
  x,
@@ -352,8 +352,6 @@ class ExecutionSession:
352
352
  condition: Callable,
353
353
  ) -> None:
354
354
  """
355
- EXPERIMENTAL
356
-
357
355
  When simulating on a statevector simulator, emulate the behavior of postprocessing
358
356
  by discarding amplitudes for which their states are "undesirable".
359
357
 
classiq/execution/iqcc.py CHANGED
@@ -2,12 +2,49 @@ import time
2
2
  import webbrowser
3
3
 
4
4
  from classiq.interface.exceptions import ClassiqError
5
- from classiq.interface.execution.iqcc import IQCCInitAuthData, IQCCProbeAuthData
5
+ from classiq.interface.execution.iqcc import (
6
+ IQCCAuthItemDetails,
7
+ IQCCInitAuthData,
8
+ IQCCListAuthMethods,
9
+ IQCCListAuthTargets,
10
+ IQCCProbeAuthData,
11
+ )
6
12
 
7
13
  from classiq._internals.api_wrapper import ApiWrapper
8
14
  from classiq._internals.async_utils import syncify_function
9
15
 
10
16
 
17
+ async def list_iqcc_auth_scopes_async() -> list[IQCCAuthItemDetails]:
18
+ """List available authentication scopes in IQCC Bounday.
19
+
20
+ Returns:
21
+ The available authentication scopes.
22
+ """
23
+ response = await ApiWrapper().call_iqcc_list_auth_scopes()
24
+ return response.items
25
+
26
+
27
+ list_iqcc_auth_scopes = syncify_function(list_iqcc_auth_scopes_async)
28
+
29
+
30
+ async def list_iqcc_auth_methods_async(auth_scope_id: str) -> list[IQCCAuthItemDetails]:
31
+ """List available authentication methods in IQCC Bounday for a specific scope.
32
+
33
+ Args:
34
+ auth_scope_id: The ID of the IQCC Boundary authentication scope.
35
+
36
+ Returns:
37
+ The available authentication methods.
38
+ """
39
+ response = await ApiWrapper().call_iqcc_list_auth_methods(
40
+ IQCCListAuthMethods(auth_scope_id=auth_scope_id)
41
+ )
42
+ return response.items
43
+
44
+
45
+ list_iqcc_auth_methods = syncify_function(list_iqcc_auth_methods_async)
46
+
47
+
11
48
  async def generate_iqcc_token_async(
12
49
  auth_scope_id: str,
13
50
  auth_method_id: str,
@@ -61,3 +98,31 @@ async def generate_iqcc_token_async(
61
98
 
62
99
 
63
100
  generate_iqcc_token = syncify_function(generate_iqcc_token_async)
101
+
102
+
103
+ async def list_iqcc_auth_targets_async(
104
+ auth_scope_id: str,
105
+ auth_method_id: str,
106
+ auth_token: str,
107
+ ) -> list[IQCCAuthItemDetails]:
108
+ """List available authentication targets in IQCC Boundary for the user.
109
+
110
+ Args:
111
+ auth_scope_id: The ID of the IQCC Boundary authentication scope.
112
+ auth_method_id: The ID of the IQCC Boundary authentication method.
113
+ auth_token: The authentication token string returned from `generate_iqcc_token_async`.
114
+
115
+ Returns:
116
+ The available authentication targets.
117
+ """
118
+ response = await ApiWrapper().call_iqcc_list_auth_targets(
119
+ IQCCListAuthTargets(
120
+ auth_scope_id=auth_scope_id,
121
+ auth_method_id=auth_method_id,
122
+ auth_token=auth_token,
123
+ )
124
+ )
125
+ return response.items
126
+
127
+
128
+ list_iqcc_auth_target = syncify_function(list_iqcc_auth_targets_async)
@@ -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.65.4'
6
+ SEMVER_VERSION = '0.66.1'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -1,15 +1,29 @@
1
- from typing import Optional
1
+ from typing import Optional, TypeVar
2
+ from uuid import UUID
2
3
 
3
4
  import pydantic
5
+ from typing_extensions import Self
4
6
 
5
7
  from classiq.interface.helpers.hashable_pydantic_base_model import (
6
8
  HashablePydanticBaseModel,
7
9
  )
8
10
  from classiq.interface.source_reference import SourceReference
9
11
 
12
+ ASTNodeType = TypeVar("ASTNodeType", bound="ASTNode")
13
+
10
14
 
11
15
  class ASTNode(HashablePydanticBaseModel):
12
16
  source_ref: Optional[SourceReference] = pydantic.Field(default=None)
17
+ back_ref: Optional[UUID] = pydantic.Field(default=None)
18
+
19
+ def _as_back_ref(self: Self) -> Self:
20
+ return self
21
+
22
+
23
+ def without_statement_blocks(
24
+ ast_node: ASTNodeType, statement_block_fields: list[str]
25
+ ) -> ASTNodeType:
26
+ return ast_node.model_copy(update={field: [] for field in statement_block_fields})
13
27
 
14
28
 
15
29
  class HashableASTNode(ASTNode, HashablePydanticBaseModel):
@@ -161,20 +161,6 @@ class ClassiqBackendPreferences(BackendPreferences):
161
161
  def is_nvidia_backend(self) -> bool:
162
162
  return self.backend_name in list(ClassiqNvidiaBackendNames)
163
163
 
164
- # CAD-25390
165
- @pydantic.field_validator("backend_name")
166
- @classmethod
167
- def _validate_nvidia_name_backwards_compatibility(cls, backend_name: str) -> str:
168
- if backend_name == "nvidia_state_vector_simulator":
169
- warnings.warn(
170
- "The name 'nvidia_state_vector_simulator' is deprecated and "
171
- "will be removed soon, no earlier than January 12th 2025. "
172
- "Please use ClassiqNvidiaBackendNames.SIMULATOR instead",
173
- ClassiqDeprecationWarning,
174
- stacklevel=2,
175
- )
176
- return backend_name
177
-
178
164
 
179
165
  class AwsBackendPreferences(BackendPreferences):
180
166
  """
@@ -10,6 +10,7 @@ from classiq.interface.generator.generated_circuit_data import (
10
10
  FunctionDebugInfoInterface,
11
11
  OperationLevel,
12
12
  )
13
+ from classiq.interface.model.statement_block import ConcreteQuantumStatement
13
14
 
14
15
  ParameterValue = Union[float, int, str, None]
15
16
 
@@ -32,6 +33,7 @@ class FunctionDebugInfo(BaseModel):
32
33
  is_allocate_or_free: bool = Field(default=False)
33
34
  is_inverse: bool = Field(default=False)
34
35
  port_to_passed_variable_map: dict[str, str] = Field(default_factory=dict)
36
+ node: Optional[ConcreteQuantumStatement] = None
35
37
 
36
38
  @staticmethod
37
39
  def param_controller(value: Any) -> str:
@@ -1,3 +1,7 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, Field
4
+
1
5
  from classiq.interface.helpers.versioned_model import VersionedModel
2
6
 
3
7
 
@@ -17,3 +21,24 @@ class IQCCProbeAuthData(IQCCInitAuthData):
17
21
 
18
22
  class IQCCProbeAuthResponse(VersionedModel):
19
23
  auth_token: str
24
+
25
+
26
+ class IQCCAuthItemDetails(BaseModel):
27
+ id: str
28
+ name: str
29
+ description: str
30
+ scope_id: Optional[str] = Field(default=None)
31
+
32
+
33
+ class IQCCAuthItemsDetails(VersionedModel):
34
+ items: list[IQCCAuthItemDetails]
35
+
36
+
37
+ class IQCCListAuthMethods(VersionedModel):
38
+ auth_scope_id: str
39
+
40
+
41
+ class IQCCListAuthTargets(VersionedModel):
42
+ auth_scope_id: str
43
+ auth_method_id: str
44
+ auth_token: str
@@ -3,10 +3,7 @@ from typing import TYPE_CHECKING, Any, Union
3
3
 
4
4
  from sympy import Integer
5
5
 
6
- from classiq.interface.exceptions import (
7
- ClassiqInternalExpansionError,
8
- ClassiqValueError,
9
- )
6
+ from classiq.interface.exceptions import ClassiqValueError
10
7
  from classiq.interface.generator.expressions.expression import Expression
11
8
  from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
12
9
  from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
@@ -45,9 +42,6 @@ class QmodQArrayProxy(NonSymbolicExpr, QmodSizedProxy):
45
42
  def _get_subscript(self, index: Union[int, Integer]) -> "QmodSizedProxy":
46
43
  if isinstance(index, Integer):
47
44
  index = int(index)
48
- if index < 0 or index >= self._length:
49
- raise ClassiqInternalExpansionError
50
-
51
45
  return self._element_type.get_proxy(
52
46
  SubscriptHandleBinding(
53
47
  base_handle=self.handle,
@@ -64,12 +58,6 @@ class QmodQArrayProxy(NonSymbolicExpr, QmodSizedProxy):
64
58
  slice_ = slice(slice_.start, int(slice_.stop))
65
59
  if not isinstance(slice_.start, int) or not isinstance(slice_.stop, int):
66
60
  raise ClassiqValueError(ILLEGAL_SLICE_MSG)
67
- if (
68
- slice_.start >= slice_.stop
69
- or slice_.start < 0
70
- or slice_.stop > self._length
71
- ):
72
- raise ClassiqInternalExpansionError
73
61
 
74
62
  return QmodQArrayProxy(
75
63
  SlicedHandleBinding(
@@ -1,5 +1,6 @@
1
1
  from collections import abc, defaultdict
2
2
  from collections.abc import Collection, Mapping, Sequence
3
+ from functools import partial
3
4
  from typing import (
4
5
  TYPE_CHECKING,
5
6
  Any,
@@ -90,12 +91,14 @@ class Transformer(Visitor):
90
91
  ) -> defaultdict[Key, RetType]:
91
92
  new_default_factory: Callable[[], RetType] | None = None
92
93
  if (default_factory := node.default_factory) is not None:
93
-
94
- def new_default_factory() -> RetType:
95
- return self.visit(default_factory()) # type: ignore[misc]
96
-
94
+ new_default_factory = partial(
95
+ self._new_default_factory, default_factory=default_factory
96
+ )
97
97
  return defaultdict(new_default_factory, self.visit_dict(node))
98
98
 
99
+ def _new_default_factory(self, default_factory: Callable[[], NodeType]) -> RetType:
100
+ return self.visit(default_factory())
101
+
99
102
  def visit_tuple(self, node: tuple[NodeType, ...]) -> tuple[RetType, ...]:
100
103
  return tuple(self.visit(value) for value in node)
101
104
 
@@ -1,5 +1,6 @@
1
1
  from typing import TYPE_CHECKING, Literal
2
2
 
3
+ from classiq.interface.ast_node import ASTNodeType, without_statement_blocks
3
4
  from classiq.interface.generator.expressions.expression import Expression
4
5
  from classiq.interface.model.quantum_statement import QuantumOperation
5
6
 
@@ -13,3 +14,6 @@ class ClassicalIf(QuantumOperation):
13
14
  condition: Expression
14
15
  then: "StatementBlock"
15
16
  else_: "StatementBlock"
17
+
18
+ def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
19
+ return without_statement_blocks(self, ["then", "else_"])
@@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Literal, Optional
2
2
 
3
3
  import pydantic
4
4
 
5
+ from classiq.interface.ast_node import ASTNodeType, without_statement_blocks
5
6
  from classiq.interface.generator.arith.arithmetic import compute_arithmetic_result_type
6
7
  from classiq.interface.model.quantum_expressions.quantum_expression import (
7
8
  QuantumExpressionOperation,
@@ -43,3 +44,6 @@ class Control(QuantumExpressionOperation):
43
44
  self._result_type = compute_arithmetic_result_type(
44
45
  self.expression.expr, var_types, machine_precision
45
46
  )
47
+
48
+ def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
49
+ return without_statement_blocks(self, ["body", "else_block"])
@@ -1,5 +1,6 @@
1
1
  from typing import TYPE_CHECKING, Literal
2
2
 
3
+ from classiq.interface.ast_node import ASTNodeType, without_statement_blocks
3
4
  from classiq.interface.model.quantum_statement import QuantumOperation
4
5
 
5
6
  if TYPE_CHECKING:
@@ -10,3 +11,6 @@ class Invert(QuantumOperation):
10
11
  kind: Literal["Invert"]
11
12
 
12
13
  body: "StatementBlock"
14
+
15
+ def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
16
+ return without_statement_blocks(self, ["body"])
@@ -1,6 +1,6 @@
1
1
  from collections import Counter
2
2
  from collections.abc import Mapping
3
- from typing import Any, Literal, NewType
3
+ from typing import Any, Literal, NewType, Optional
4
4
 
5
5
  import pydantic
6
6
 
@@ -9,6 +9,7 @@ from classiq.interface.debug_info.debug_info import DebugInfoCollection
9
9
  from classiq.interface.exceptions import ClassiqValueError
10
10
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
11
11
  from classiq.interface.generator.constant import Constant
12
+ from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
12
13
  from classiq.interface.generator.functions.port_declaration import (
13
14
  PortDeclarationDirection,
14
15
  )
@@ -102,6 +103,7 @@ class Model(VersionedModel, ASTNode):
102
103
  functions_compilation_metadata: dict[str, CompilationMetadata] = pydantic.Field(
103
104
  default_factory=dict
104
105
  )
106
+ execution_parameters: Optional[dict[str, ConcreteClassicalType]] = None
105
107
 
106
108
  @property
107
109
  def main_func(self) -> NativeFunctionDefinition:
@@ -0,0 +1,14 @@
1
+ from classiq.interface.debug_info.debug_info import DebugInfoCollection
2
+ from classiq.interface.generator.visitor import Transformer, Visitor
3
+
4
+
5
+ class ModelVisitor(Visitor):
6
+ def visit_DebugInfoCollection(self, debug_info: DebugInfoCollection) -> None:
7
+ return
8
+
9
+
10
+ class ModelTransformer(Transformer):
11
+ def visit_DebugInfoCollection(
12
+ self, debug_info: DebugInfoCollection
13
+ ) -> DebugInfoCollection:
14
+ return debug_info
@@ -1,5 +1,6 @@
1
1
  from typing import TYPE_CHECKING, Literal
2
2
 
3
+ from classiq.interface.ast_node import ASTNodeType, without_statement_blocks
3
4
  from classiq.interface.generator.expressions.expression import Expression
4
5
  from classiq.interface.model.quantum_statement import QuantumOperation
5
6
 
@@ -12,3 +13,6 @@ class Power(QuantumOperation):
12
13
 
13
14
  power: Expression
14
15
  body: "StatementBlock"
16
+
17
+ def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
18
+ return without_statement_blocks(self, ["body"])
@@ -17,6 +17,9 @@ from classiq.interface.model.handle_binding import (
17
17
  class QuantumStatement(ASTNode):
18
18
  kind: str
19
19
  model_config = ConfigDict(extra="forbid")
20
+ uuid: UUID = pydantic.Field(
21
+ description="A unique identifier for this operation", default_factory=uuid4
22
+ )
20
23
 
21
24
  @pydantic.model_validator(mode="before")
22
25
  @classmethod
@@ -31,9 +34,6 @@ class HandleMetadata:
31
34
 
32
35
 
33
36
  class QuantumOperation(QuantumStatement):
34
- uuid: UUID = pydantic.Field(
35
- description="A unique identifier for this operation", default_factory=uuid4
36
- )
37
37
  _generative_blocks: dict[str, Callable] = pydantic.PrivateAttr(default_factory=dict)
38
38
 
39
39
  @property
@@ -1,5 +1,6 @@
1
1
  from typing import TYPE_CHECKING, Literal
2
2
 
3
+ from classiq.interface.ast_node import ASTNodeType, without_statement_blocks
3
4
  from classiq.interface.generator.expressions.expression import Expression
4
5
  from classiq.interface.model.quantum_statement import QuantumOperation
5
6
 
@@ -13,3 +14,6 @@ class Repeat(QuantumOperation):
13
14
  iter_var: str
14
15
  count: Expression
15
16
  body: "StatementBlock"
17
+
18
+ def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
19
+ return without_statement_blocks(self, ["body"])
@@ -1,5 +1,6 @@
1
1
  from typing import TYPE_CHECKING, Literal
2
2
 
3
+ from classiq.interface.ast_node import ASTNodeType, without_statement_blocks
3
4
  from classiq.interface.model.quantum_statement import QuantumOperation
4
5
 
5
6
  if TYPE_CHECKING:
@@ -11,3 +12,6 @@ class WithinApply(QuantumOperation):
11
12
 
12
13
  compute: "StatementBlock"
13
14
  action: "StatementBlock"
15
+
16
+ def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
17
+ return without_statement_blocks(self, ["compute", "action"])
@@ -82,3 +82,9 @@ IQCC_INIT_AUTH_SUFFIX = "/init_auth"
82
82
  IQCC_INIT_AUTH_FULL_PATH = IQCC_PREFIX + IQCC_INIT_AUTH_SUFFIX
83
83
  IQCC_PROBE_AUTH_SUFFIX = "/probe_auth"
84
84
  IQCC_PROBE_AUTH_FULL_PATH = IQCC_PREFIX + IQCC_PROBE_AUTH_SUFFIX
85
+ IQCC_LIST_AUTH_SCOPES_SUFFIX = "/auth_scopes"
86
+ IQCC_LIST_AUTH_SCOPES_FULL_PATH = IQCC_PREFIX + IQCC_LIST_AUTH_SCOPES_SUFFIX
87
+ IQCC_LIST_AUTH_METHODS_SUFFIX = "/auth_methods"
88
+ IQCC_LIST_AUTH_METHODS_FULL_PATH = IQCC_PREFIX + IQCC_LIST_AUTH_METHODS_SUFFIX
89
+ IQCC_LIST_AUTH_TARGETS_SUFFIX = "/auth_targets"
90
+ IQCC_LIST_AUTH_TARGETS_FULL_PATH = IQCC_PREFIX + IQCC_LIST_AUTH_TARGETS_SUFFIX
@@ -17,7 +17,6 @@ from classiq.interface.model.quantum_lambda_function import QuantumCallable
17
17
  from classiq.interface.model.quantum_statement import QuantumStatement
18
18
 
19
19
  from classiq.model_expansions.capturing.captured_vars import CapturedVars
20
- from classiq.model_expansions.expression_renamer import ExpressionRenamer
21
20
  from classiq.model_expansions.scope import (
22
21
  Evaluated,
23
22
  QuantumSymbol,
@@ -84,20 +83,10 @@ class FunctionClosure(Closure):
84
83
  scope: Scope,
85
84
  body: Optional[Sequence[QuantumStatement]] = None,
86
85
  positional_arg_declarations: Sequence[PositionalArg] = tuple(),
87
- expr_renamer: Optional[ExpressionRenamer] = None,
88
86
  is_lambda: bool = False,
89
87
  is_atomic: bool = False,
90
88
  **kwargs: Any,
91
89
  ) -> Self:
92
- if expr_renamer:
93
- positional_arg_declarations = (
94
- expr_renamer.rename_positional_arg_declarations(
95
- positional_arg_declarations
96
- )
97
- )
98
- if body is not None:
99
- body = expr_renamer.visit(body)
100
-
101
90
  blocks = {"body": body} if body is not None else {}
102
91
  return cls(
103
92
  name,