classiq 0.65.4__py3-none-any.whl → 0.66.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.
- classiq/_internals/api_wrapper.py +43 -0
- classiq/applications/qnn/qlayer.py +65 -3
- classiq/execution/execution_session.py +0 -2
- classiq/execution/iqcc.py +66 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/ast_node.py +15 -1
- classiq/interface/backend/backend_preferences.py +0 -14
- classiq/interface/debug_info/debug_info.py +2 -0
- classiq/interface/execution/iqcc.py +25 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +1 -13
- classiq/interface/generator/visitor.py +7 -4
- classiq/interface/model/classical_if.py +4 -0
- classiq/interface/model/control.py +4 -0
- classiq/interface/model/invert.py +4 -0
- classiq/interface/model/model.py +3 -1
- classiq/interface/model/model_visitor.py +14 -0
- classiq/interface/model/power.py +4 -0
- classiq/interface/model/quantum_statement.py +3 -3
- classiq/interface/model/repeat.py +4 -0
- classiq/interface/model/within_apply_operation.py +4 -0
- classiq/interface/server/routes.py +6 -0
- classiq/model_expansions/closure.py +0 -11
- classiq/model_expansions/evaluators/quantum_type_utils.py +6 -6
- classiq/model_expansions/expression_evaluator.py +10 -1
- classiq/model_expansions/interpreters/base_interpreter.py +28 -18
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +58 -1
- classiq/model_expansions/interpreters/generative_interpreter.py +7 -13
- classiq/model_expansions/quantum_operations/allocate.py +69 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +7 -6
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +4 -4
- classiq/model_expansions/quantum_operations/emitter.py +2 -15
- classiq/model_expansions/quantum_operations/quantum_function_call.py +22 -0
- classiq/model_expansions/quantum_operations/shallow_emitter.py +21 -35
- classiq/model_expansions/scope_initialization.py +49 -34
- classiq/model_expansions/transformers/model_renamer.py +98 -0
- classiq/model_expansions/transformers/var_splitter.py +7 -82
- classiq/open_library/functions/grover.py +5 -5
- classiq/qmod/builtins/__init__.py +1 -1
- classiq/qmod/builtins/functions/__init__.py +0 -2
- classiq/qmod/builtins/functions/allocation.py +1 -26
- classiq/qmod/builtins/operations.py +12 -6
- classiq/qmod/generative.py +6 -4
- classiq/qmod/native/pretty_printer.py +3 -2
- classiq/qmod/pretty_print/pretty_printer.py +3 -1
- classiq/qmod/qmod_variable.py +6 -1
- classiq/qmod/semantics/annotation/call_annotation.py +30 -2
- classiq/qmod/semantics/annotation/qstruct_annotator.py +2 -2
- classiq/qmod/semantics/error_manager.py +20 -6
- classiq/qmod/semantics/static_semantics_visitor.py +3 -40
- classiq/qmod/semantics/validation/constants_validation.py +2 -3
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +6 -9
- classiq/qmod/semantics/validation/main_validation.py +2 -3
- classiq/qmod/semantics/validation/model_validation.py +25 -0
- classiq/qmod/semantics/validation/signature_validation.py +24 -0
- classiq/qmod/semantics/validation/types_validation.py +45 -46
- classiq/qmod/utilities.py +12 -0
- {classiq-0.65.4.dist-info → classiq-0.66.0.dist-info}/METADATA +1 -1
- {classiq-0.65.4.dist-info → classiq-0.66.0.dist-info}/RECORD +59 -55
- classiq/model_expansions/expression_renamer.py +0 -76
- {classiq-0.65.4.dist-info → classiq-0.66.0.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
|
-
|
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
|
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)
|
classiq/interface/_version.py
CHANGED
classiq/interface/ast_node.py
CHANGED
@@ -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
|
-
|
95
|
-
|
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"])
|
classiq/interface/model/model.py
CHANGED
@@ -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
|
classiq/interface/model/power.py
CHANGED
@@ -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,
|