classiq 0.67.0__py3-none-any.whl → 0.68.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 +5 -1
- classiq/_internals/async_utils.py +1 -1
- classiq/_internals/authentication/password_manager.py +1 -1
- classiq/_internals/client.py +1 -1
- classiq/execution/execution_session.py +7 -3
- classiq/executor.py +7 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/ast_node.py +1 -1
- classiq/interface/chemistry/operator.py +1 -1
- classiq/interface/debug_info/debug_info.py +15 -0
- classiq/interface/generator/arith/arithmetic.py +96 -1
- classiq/interface/generator/arith/arithmetic_expression_parser.py +1 -1
- classiq/interface/generator/generated_circuit_data.py +4 -2
- classiq/interface/generator/quantum_program.py +18 -1
- classiq/interface/generator/types/enum_declaration.py +33 -2
- classiq/interface/model/classical_if.py +2 -2
- classiq/interface/model/control.py +2 -2
- classiq/interface/model/invert.py +2 -2
- classiq/interface/model/power.py +2 -2
- classiq/interface/model/quantum_function_call.py +4 -0
- classiq/interface/model/repeat.py +2 -2
- classiq/interface/model/statement_block.py +1 -1
- classiq/interface/model/within_apply_operation.py +2 -2
- classiq/model_expansions/interpreters/generative_interpreter.py +78 -18
- classiq/model_expansions/quantum_operations/allocate.py +3 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +52 -0
- classiq/model_expansions/quantum_operations/bind.py +2 -1
- classiq/model_expansions/quantum_operations/block_evaluator.py +76 -0
- classiq/model_expansions/quantum_operations/classicalif.py +5 -4
- classiq/model_expansions/quantum_operations/composite_emitter.py +27 -0
- classiq/model_expansions/quantum_operations/emitter.py +16 -2
- classiq/model_expansions/quantum_operations/expression_evaluator.py +33 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +28 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +3 -2
- classiq/model_expansions/quantum_operations/repeat.py +2 -1
- classiq/model_expansions/quantum_operations/variable_decleration.py +2 -1
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +1 -1
- classiq/open_library/functions/__init__.py +1 -2
- classiq/open_library/functions/amplitude_amplification.py +8 -5
- classiq/open_library/functions/discrete_sine_cosine_transform.py +16 -13
- classiq/open_library/functions/grover.py +6 -10
- classiq/open_library/functions/modular_exponentiation.py +7 -13
- classiq/open_library/functions/state_preparation.py +16 -17
- classiq/open_library/functions/swap_test.py +1 -1
- classiq/open_library/functions/utility_functions.py +10 -2
- classiq/qmod/builtins/functions/chemistry.py +6 -38
- classiq/qmod/quantum_expandable.py +30 -6
- classiq/qmod/semantics/validation/types_validation.py +1 -1
- classiq/qmod/symbolic.py +2 -1
- classiq/qmod/utilities.py +2 -1
- classiq/qmod/write_qmod.py +10 -7
- classiq/synthesis.py +20 -7
- {classiq-0.67.0.dist-info → classiq-0.68.0.dist-info}/METADATA +1 -1
- {classiq-0.67.0.dist-info → classiq-0.68.0.dist-info}/RECORD +55 -51
- classiq/model_expansions/quantum_operations/shallow_emitter.py +0 -166
- {classiq-0.67.0.dist-info → classiq-0.68.0.dist-info}/WHEEL +0 -0
@@ -3,6 +3,7 @@ from typing import Any, Optional, Protocol, TypeVar
|
|
3
3
|
|
4
4
|
import httpx
|
5
5
|
import pydantic
|
6
|
+
from pydantic.main import IncEx
|
6
7
|
|
7
8
|
import classiq.interface.executor.execution_result
|
8
9
|
import classiq.interface.pyomo_extension
|
@@ -72,11 +73,12 @@ class ApiWrapper:
|
|
72
73
|
model: pydantic.BaseModel,
|
73
74
|
use_versioned_url: bool = True,
|
74
75
|
http_client: Optional[httpx.AsyncClient] = None,
|
76
|
+
exclude: Optional[IncEx] = None,
|
75
77
|
) -> dict:
|
76
78
|
# TODO: we can't use model.dict() - it doesn't serialize complex class.
|
77
79
|
# This was added because JSON serializer doesn't serialize complex type, and pydantic does.
|
78
80
|
# We should add support for smarter json serialization.
|
79
|
-
body = json.loads(model.model_dump_json())
|
81
|
+
body = json.loads(model.model_dump_json(exclude=exclude))
|
80
82
|
return await cls._call_task(
|
81
83
|
http_method,
|
82
84
|
url,
|
@@ -135,6 +137,7 @@ class ApiWrapper:
|
|
135
137
|
url=routes.EXECUTION_SESSIONS_PREFIX,
|
136
138
|
model=circuit,
|
137
139
|
http_client=http_client,
|
140
|
+
exclude={"debug_info"},
|
138
141
|
)
|
139
142
|
return raw_result["id"]
|
140
143
|
|
@@ -164,6 +167,7 @@ class ApiWrapper:
|
|
164
167
|
url=routes.CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_FULL,
|
165
168
|
model=circuit,
|
166
169
|
http_client=http_client,
|
170
|
+
exclude={"debug_info"},
|
167
171
|
)
|
168
172
|
|
169
173
|
@classmethod
|
@@ -58,7 +58,7 @@ def enable_jupyter_notebook() -> None:
|
|
58
58
|
|
59
59
|
|
60
60
|
def _make_iterable_interval(
|
61
|
-
interval_sec: Union[SupportsFloat, Iterable[SupportsFloat]]
|
61
|
+
interval_sec: Union[SupportsFloat, Iterable[SupportsFloat]],
|
62
62
|
) -> Iterable[float]:
|
63
63
|
if isinstance(interval_sec, Iterable):
|
64
64
|
return map(float, interval_sec)
|
@@ -117,7 +117,7 @@ class DummyPasswordManager(PasswordManager):
|
|
117
117
|
|
118
118
|
class FilePasswordManager(PasswordManager):
|
119
119
|
_CLASSIQ_CREDENTIALS_FILE_PATH: str = "{}/.classiq-credentials".format(
|
120
|
-
os.getenv("HOME")
|
120
|
+
os.getenv("CLASSIQ_DIR", os.getenv("HOME"))
|
121
121
|
)
|
122
122
|
|
123
123
|
def __init__(self) -> None:
|
classiq/_internals/client.py
CHANGED
@@ -89,7 +89,7 @@ P = ParamSpec("P")
|
|
89
89
|
|
90
90
|
|
91
91
|
def try_again_on_failure(
|
92
|
-
func: Callable[P, Awaitable[Ret]]
|
92
|
+
func: Callable[P, Awaitable[Ret]],
|
93
93
|
) -> Callable[P, Awaitable[Ret]]:
|
94
94
|
def check_approved_api_error(error_message: str) -> bool:
|
95
95
|
for approved_api_error in APPROVED_API_ERROR_MESSAGES_FOR_RESTART:
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import json
|
2
1
|
import random
|
3
2
|
from types import TracebackType
|
4
3
|
from typing import Callable, Optional, Union, cast
|
@@ -16,7 +15,10 @@ from classiq.interface.executor.result import (
|
|
16
15
|
)
|
17
16
|
from classiq.interface.generator.arith import number_utils
|
18
17
|
from classiq.interface.generator.functions.qmod_python_interface import QmodPyStruct
|
19
|
-
from classiq.interface.generator.quantum_program import
|
18
|
+
from classiq.interface.generator.quantum_program import (
|
19
|
+
OMIT_DEBUG_INFO_FLAG,
|
20
|
+
QuantumProgram,
|
21
|
+
)
|
20
22
|
from classiq.interface.model.quantum_type import QuantumBit, QuantumNumeric
|
21
23
|
|
22
24
|
from classiq._internals import async_utils
|
@@ -46,7 +48,9 @@ def _deserialize_program(program: Program) -> QuantumProgram:
|
|
46
48
|
return (
|
47
49
|
program
|
48
50
|
if isinstance(program, QuantumProgram)
|
49
|
-
else QuantumProgram.
|
51
|
+
else QuantumProgram.model_validate_json(
|
52
|
+
program, context={OMIT_DEBUG_INFO_FLAG: True}
|
53
|
+
)
|
50
54
|
)
|
51
55
|
|
52
56
|
|
classiq/executor.py
CHANGED
@@ -10,7 +10,10 @@ from classiq.interface.executor.execution_preferences import ExecutionPreference
|
|
10
10
|
from classiq.interface.executor.quantum_code import QuantumCode
|
11
11
|
from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
|
12
12
|
from classiq.interface.executor.result import ExecutionDetails
|
13
|
-
from classiq.interface.generator.quantum_program import
|
13
|
+
from classiq.interface.generator.quantum_program import (
|
14
|
+
OMIT_DEBUG_INFO_FLAG,
|
15
|
+
QuantumProgram,
|
16
|
+
)
|
14
17
|
|
15
18
|
from classiq._internals import async_utils
|
16
19
|
from classiq._internals.api_wrapper import ApiWrapper
|
@@ -27,7 +30,9 @@ BackendPreferencesAndResult: TypeAlias = tuple[
|
|
27
30
|
def _parse_serialized_qprog(
|
28
31
|
quantum_program: SerializedQuantumProgram,
|
29
32
|
) -> QuantumProgram:
|
30
|
-
return QuantumProgram.model_validate_json(
|
33
|
+
return QuantumProgram.model_validate_json(
|
34
|
+
quantum_program, context={OMIT_DEBUG_INFO_FLAG: True}
|
35
|
+
)
|
31
36
|
|
32
37
|
|
33
38
|
async def execute_async(quantum_program: SerializedQuantumProgram) -> ExecutionJob:
|
classiq/interface/_version.py
CHANGED
classiq/interface/ast_node.py
CHANGED
@@ -20,7 +20,7 @@ class ASTNode(HashablePydanticBaseModel):
|
|
20
20
|
return self
|
21
21
|
|
22
22
|
|
23
|
-
def
|
23
|
+
def reset_lists(
|
24
24
|
ast_node: ASTNodeType, statement_block_fields: list[str]
|
25
25
|
) -> ASTNodeType:
|
26
26
|
return ast_node.model_copy(update={field: [] for field in statement_block_fields})
|
@@ -69,7 +69,7 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
69
69
|
|
70
70
|
@staticmethod
|
71
71
|
def _validate_monomial_coefficient(
|
72
|
-
coeff: Union[sympy.Expr, ParameterComplexType]
|
72
|
+
coeff: Union[sympy.Expr, ParameterComplexType],
|
73
73
|
) -> ParameterComplexType:
|
74
74
|
if isinstance(coeff, str):
|
75
75
|
validate_expression_str(coeff)
|
@@ -89,6 +89,21 @@ class DebugInfoCollection(BaseModel):
|
|
89
89
|
return self.blackbox_data.get(debug_info.name)
|
90
90
|
|
91
91
|
|
92
|
+
def get_back_refs(
|
93
|
+
debug_info: FunctionDebugInfo, collected_debug_info: DebugInfoCollection
|
94
|
+
) -> list[ConcreteQuantumStatement]:
|
95
|
+
back_refs: list[ConcreteQuantumStatement] = []
|
96
|
+
while (node := debug_info.node) is not None:
|
97
|
+
back_refs.insert(0, node)
|
98
|
+
if node.back_ref is None:
|
99
|
+
break
|
100
|
+
next_debug_info = collected_debug_info.get(node.back_ref)
|
101
|
+
if next_debug_info is None:
|
102
|
+
break
|
103
|
+
debug_info = next_debug_info
|
104
|
+
return back_refs
|
105
|
+
|
106
|
+
|
92
107
|
def new_function_debug_info_by_node(
|
93
108
|
node: ConcreteQuantumStatement,
|
94
109
|
) -> FunctionDebugInfo:
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
import ast
|
2
|
+
from typing import Any, Final, Optional, cast
|
2
3
|
|
3
4
|
import networkx as nx
|
4
5
|
import pydantic
|
@@ -95,6 +96,9 @@ def get_arithmetic_params(
|
|
95
96
|
machine_precision: int,
|
96
97
|
enable_target: bool = False,
|
97
98
|
) -> Arithmetic:
|
99
|
+
expr_str, var_types = _substitute_quantum_subscripts(
|
100
|
+
expr_str, var_types, machine_precision
|
101
|
+
)
|
98
102
|
return Arithmetic(
|
99
103
|
expression=expr_str,
|
100
104
|
definitions={
|
@@ -121,3 +125,94 @@ def compute_arithmetic_result_type(
|
|
121
125
|
return register_info_to_quantum_type(
|
122
126
|
arith_param.outputs[ARITHMETIC_EXPRESSION_RESULT_NAME]
|
123
127
|
)
|
128
|
+
|
129
|
+
|
130
|
+
def aggregate_numeric_types(
|
131
|
+
numeric_types: list[QuantumNumeric],
|
132
|
+
) -> RegisterArithmeticInfo:
|
133
|
+
if all(
|
134
|
+
numeric_type.size_in_bits == 1
|
135
|
+
and numeric_type.sign_value
|
136
|
+
and numeric_type.fraction_digits_value == 1
|
137
|
+
for numeric_type in numeric_types
|
138
|
+
):
|
139
|
+
return RegisterArithmeticInfo(size=1, is_signed=True, fraction_places=1)
|
140
|
+
int_size = max(
|
141
|
+
numeric_type.size_in_bits
|
142
|
+
- int(numeric_type.sign_value)
|
143
|
+
- numeric_type.fraction_digits_value
|
144
|
+
for numeric_type in numeric_types
|
145
|
+
)
|
146
|
+
is_signed = any(numeric_type.sign_value for numeric_type in numeric_types)
|
147
|
+
frac_size = max(
|
148
|
+
numeric_type.fraction_digits_value for numeric_type in numeric_types
|
149
|
+
)
|
150
|
+
total_size = int_size + int(is_signed) + frac_size
|
151
|
+
return RegisterArithmeticInfo(
|
152
|
+
size=total_size, is_signed=is_signed, fraction_places=frac_size
|
153
|
+
)
|
154
|
+
|
155
|
+
|
156
|
+
class _QuantumSubscriptRemover(ast.NodeTransformer):
|
157
|
+
def __init__(self, machine_precision: int) -> None:
|
158
|
+
self._machine_precision = machine_precision
|
159
|
+
self.substitutions_types: dict[str, QuantumNumeric] = {}
|
160
|
+
|
161
|
+
def visit_Call(self, node: ast.Call) -> ast.expr:
|
162
|
+
if not isinstance(node.func, ast.Name) or node.func.id != "Piecewise":
|
163
|
+
return node
|
164
|
+
items = [
|
165
|
+
cast(float, cast(ast.Num, cast(ast.Tuple, arg).elts[0]).value)
|
166
|
+
for arg in node.args
|
167
|
+
]
|
168
|
+
numeric_types = [
|
169
|
+
compute_arithmetic_result_type(str(num), {}, self._machine_precision)
|
170
|
+
for num in items
|
171
|
+
]
|
172
|
+
unified_numeric_type = register_info_to_quantum_type(
|
173
|
+
aggregate_numeric_types(numeric_types)
|
174
|
+
)
|
175
|
+
substitution_var_name = f"__lut__{len(self.substitutions_types)}__"
|
176
|
+
self.substitutions_types[substitution_var_name] = unified_numeric_type
|
177
|
+
return ast.Name(id=substitution_var_name)
|
178
|
+
|
179
|
+
|
180
|
+
class _NameCollector(ast.NodeVisitor):
|
181
|
+
def __init__(self) -> None:
|
182
|
+
self.names: set[str] = set()
|
183
|
+
|
184
|
+
def visit_Name(self, node: ast.Name) -> None:
|
185
|
+
self.names.add(node.id)
|
186
|
+
|
187
|
+
|
188
|
+
def _substitute_quantum_subscripts(
|
189
|
+
expr_str: str, var_types: dict[str, QuantumType], machine_precision: int
|
190
|
+
) -> tuple[str, dict[str, QuantumType]]:
|
191
|
+
"""
|
192
|
+
Remove quantum lookup expressions ([1, 2, 3, 4][n]) from an arithmetic expression
|
193
|
+
for the purpose of calculating its numeric attributes.
|
194
|
+
Each quantum lookup expression is replaced by a numeric value with equivalent
|
195
|
+
numeric properties.
|
196
|
+
|
197
|
+
Args:
|
198
|
+
expr_str: arithmetic expression
|
199
|
+
var_types: quantum variable type mapping
|
200
|
+
machine_precision: global machine precision
|
201
|
+
|
202
|
+
Returns:
|
203
|
+
1. the reduced expression
|
204
|
+
2. updated type mapping
|
205
|
+
"""
|
206
|
+
expr_ast = ast.parse(expr_str)
|
207
|
+
subscript_remover = _QuantumSubscriptRemover(machine_precision)
|
208
|
+
expr_ast = subscript_remover.visit(expr_ast)
|
209
|
+
var_types_substituted = var_types | subscript_remover.substitutions_types
|
210
|
+
expr_str_substituted = ast.unparse(expr_ast)
|
211
|
+
names_collector = _NameCollector()
|
212
|
+
names_collector.visit(ast.parse(expr_str_substituted))
|
213
|
+
var_types_substituted = {
|
214
|
+
var_name: var_type
|
215
|
+
for var_name, var_type in var_types_substituted.items()
|
216
|
+
if var_name in names_collector.names
|
217
|
+
}
|
218
|
+
return expr_str_substituted, var_types_substituted
|
@@ -11,6 +11,7 @@ from classiq.interface.generator.register_role import RegisterRole
|
|
11
11
|
from classiq.interface.generator.synthesis_metadata.synthesis_execution_data import (
|
12
12
|
ExecutionData,
|
13
13
|
)
|
14
|
+
from classiq.interface.model.statement_block import StatementBlock
|
14
15
|
|
15
16
|
from classiq.model_expansions.capturing.mangling_utils import (
|
16
17
|
demangle_capture_name,
|
@@ -22,7 +23,7 @@ _logger = logging.getLogger(__name__)
|
|
22
23
|
ParameterName = str
|
23
24
|
IOQubitMapping: TypeAlias = dict[str, tuple[int, ...]]
|
24
25
|
|
25
|
-
CLASSIQ_HIERARCHY_SEPARATOR: Literal["
|
26
|
+
CLASSIQ_HIERARCHY_SEPARATOR: Literal["__"] = "__"
|
26
27
|
|
27
28
|
VISUALIZATION_HIDE_LIST = [
|
28
29
|
"apply_to_all",
|
@@ -136,6 +137,7 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
136
137
|
parameters: list[OperationParameter] = list()
|
137
138
|
port_to_passed_variable_map: dict[str, str] = pydantic.Field(default={})
|
138
139
|
release_by_inverse: bool = pydantic.Field(default=False)
|
140
|
+
back_refs: StatementBlock = pydantic.Field(default_factory=list)
|
139
141
|
|
140
142
|
model_config = ConfigDict(extra="allow")
|
141
143
|
# Temporary field to store the override debug info for parallel old/new visualization
|
@@ -167,7 +169,7 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
167
169
|
|
168
170
|
@staticmethod
|
169
171
|
def create_parameters_from_dict(
|
170
|
-
parameters: dict[str, str]
|
172
|
+
parameters: dict[str, str],
|
171
173
|
) -> list[OperationParameter]:
|
172
174
|
return [
|
173
175
|
OperationParameter(label=key, value=value)
|
@@ -1,9 +1,11 @@
|
|
1
1
|
import uuid
|
2
2
|
from datetime import datetime, timezone
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import Optional, Union
|
4
|
+
from typing import Any, Optional, Union
|
5
5
|
|
6
6
|
import pydantic
|
7
|
+
from pydantic import model_validator
|
8
|
+
from pydantic_core.core_schema import ValidationInfo
|
7
9
|
from typing_extensions import TypeAlias
|
8
10
|
|
9
11
|
from classiq.interface.exceptions import (
|
@@ -36,6 +38,8 @@ from classiq.interface.ide.visual_model import CircuitMetrics
|
|
36
38
|
RegisterName: TypeAlias = str
|
37
39
|
InitialConditions: TypeAlias = dict[RegisterName, int]
|
38
40
|
|
41
|
+
OMIT_DEBUG_INFO_FLAG = "omit_debug_info"
|
42
|
+
|
39
43
|
|
40
44
|
class TranspiledCircuitData(CircuitCodeInterface):
|
41
45
|
depth: int
|
@@ -71,6 +75,19 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
71
75
|
program_id: str = pydantic.Field(default_factory=get_uuid_as_str)
|
72
76
|
execution_primitives_input: Optional[PrimitivesInput] = pydantic.Field(default=None)
|
73
77
|
|
78
|
+
@model_validator(mode="before")
|
79
|
+
@classmethod
|
80
|
+
def remove_debug_info(
|
81
|
+
cls, data: dict[str, Any], info: ValidationInfo
|
82
|
+
) -> dict[str, Any]:
|
83
|
+
if (
|
84
|
+
isinstance(data, dict)
|
85
|
+
and info.context is not None
|
86
|
+
and info.context.get(OMIT_DEBUG_INFO_FLAG, False)
|
87
|
+
):
|
88
|
+
data.pop("debug_info", None)
|
89
|
+
return data
|
90
|
+
|
74
91
|
def _hardware_agnostic_program_code(self) -> CodeAndSyntax:
|
75
92
|
circuit_code = self.program_circuit.get_code_by_priority()
|
76
93
|
if circuit_code is not None:
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from collections import Counter
|
2
2
|
from enum import Enum, EnumMeta, IntEnum
|
3
|
+
from typing import Any, Callable
|
3
4
|
|
4
5
|
import pydantic
|
5
6
|
|
@@ -7,6 +8,33 @@ from classiq.interface.ast_node import HashableASTNode
|
|
7
8
|
from classiq.interface.exceptions import ClassiqValueError
|
8
9
|
|
9
10
|
|
11
|
+
def rebuild_dynamic_enum(name: str, members: dict[str, int]) -> type[IntEnum]:
|
12
|
+
"""
|
13
|
+
Rebuilds the dynamic enum from its name and members.
|
14
|
+
Returns a new enum type.
|
15
|
+
"""
|
16
|
+
new_enum = IntEnum(name, members) # type: ignore[misc]
|
17
|
+
setattr(new_enum, "__members_data__", members) # noqa: B010
|
18
|
+
setattr(new_enum, "__reduce_ex__", dynamic_enum_reduce_ex) # noqa: B010
|
19
|
+
return new_enum
|
20
|
+
|
21
|
+
|
22
|
+
def dynamic_enum_reduce_ex(
|
23
|
+
obj: Any, protocol: int
|
24
|
+
) -> tuple[Callable[..., type[IntEnum]], tuple[str, dict[str, int]]]:
|
25
|
+
"""
|
26
|
+
Custom __reduce_ex__ for dynamic enums.
|
27
|
+
This function will be used when pickling an enum type or one of its members.
|
28
|
+
"""
|
29
|
+
# Get the enum type and its member data.
|
30
|
+
enum_type = type(obj)
|
31
|
+
members = getattr(enum_type, "__members_data__", None)
|
32
|
+
if members is None:
|
33
|
+
raise ValueError("Dynamic enum is missing __members_data__ attribute")
|
34
|
+
# Return the callable and arguments needed to rebuild the enum type.
|
35
|
+
return rebuild_dynamic_enum, (enum_type.__name__, members)
|
36
|
+
|
37
|
+
|
10
38
|
class EnumDeclaration(HashableASTNode):
|
11
39
|
name: str
|
12
40
|
|
@@ -39,8 +67,11 @@ class EnumDeclaration(HashableASTNode):
|
|
39
67
|
|
40
68
|
return members
|
41
69
|
|
42
|
-
def create_enum(self) -> IntEnum:
|
43
|
-
|
70
|
+
def create_enum(self) -> type[IntEnum]:
|
71
|
+
dynamic_enum = IntEnum(self.name, self.members) # type: ignore[misc]
|
72
|
+
setattr(dynamic_enum, "__members_data__", self.members) # noqa: B010
|
73
|
+
setattr(dynamic_enum, "__reduce_ex__", dynamic_enum_reduce_ex) # noqa: B010
|
74
|
+
return dynamic_enum
|
44
75
|
|
45
76
|
|
46
77
|
def declaration_from_enum(enum_type: EnumMeta) -> EnumDeclaration:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
|
-
from classiq.interface.ast_node import ASTNodeType,
|
3
|
+
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
4
4
|
from classiq.interface.generator.expressions.expression import Expression
|
5
5
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
6
6
|
|
@@ -16,4 +16,4 @@ class ClassicalIf(QuantumOperation):
|
|
16
16
|
else_: "StatementBlock"
|
17
17
|
|
18
18
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
19
|
-
return
|
19
|
+
return reset_lists(self, ["then", "else_"])
|
@@ -2,7 +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,
|
5
|
+
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
6
6
|
from classiq.interface.generator.arith.arithmetic import compute_arithmetic_result_type
|
7
7
|
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
8
8
|
QuantumExpressionOperation,
|
@@ -46,4 +46,4 @@ class Control(QuantumExpressionOperation):
|
|
46
46
|
)
|
47
47
|
|
48
48
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
49
|
-
return
|
49
|
+
return reset_lists(self, ["body", "else_block"])
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
|
-
from classiq.interface.ast_node import ASTNodeType,
|
3
|
+
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
4
4
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
5
5
|
|
6
6
|
if TYPE_CHECKING:
|
@@ -13,4 +13,4 @@ class Invert(QuantumOperation):
|
|
13
13
|
body: "StatementBlock"
|
14
14
|
|
15
15
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
16
|
-
return
|
16
|
+
return reset_lists(self, ["body"])
|
classiq/interface/model/power.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
|
-
from classiq.interface.ast_node import ASTNodeType,
|
3
|
+
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
4
4
|
from classiq.interface.generator.expressions.expression import Expression
|
5
5
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
6
6
|
|
@@ -15,4 +15,4 @@ class Power(QuantumOperation):
|
|
15
15
|
body: "StatementBlock"
|
16
16
|
|
17
17
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
18
|
-
return
|
18
|
+
return reset_lists(self, ["body"])
|
@@ -7,6 +7,7 @@ from typing import (
|
|
7
7
|
|
8
8
|
import pydantic
|
9
9
|
|
10
|
+
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
10
11
|
from classiq.interface.exceptions import ClassiqError, ClassiqValueError
|
11
12
|
from classiq.interface.generator.expressions.expression import Expression
|
12
13
|
from classiq.interface.generator.functions.port_declaration import (
|
@@ -45,6 +46,9 @@ class QuantumFunctionCall(QuantumOperation):
|
|
45
46
|
default=None
|
46
47
|
)
|
47
48
|
|
49
|
+
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
50
|
+
return reset_lists(self, ["positional_args"])
|
51
|
+
|
48
52
|
@property
|
49
53
|
def func_decl(self) -> QuantumFunctionDeclaration:
|
50
54
|
if self._func_decl is None:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
|
-
from classiq.interface.ast_node import ASTNodeType,
|
3
|
+
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
4
4
|
from classiq.interface.generator.expressions.expression import Expression
|
5
5
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
6
6
|
|
@@ -16,4 +16,4 @@ class Repeat(QuantumOperation):
|
|
16
16
|
body: "StatementBlock"
|
17
17
|
|
18
18
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
19
|
-
return
|
19
|
+
return reset_lists(self, ["body"])
|
@@ -27,8 +27,8 @@ from classiq.interface.model.within_apply_operation import WithinApply
|
|
27
27
|
|
28
28
|
ConcreteQuantumStatement = Annotated[
|
29
29
|
Union[
|
30
|
-
Allocate,
|
31
30
|
QuantumFunctionCall,
|
31
|
+
Allocate,
|
32
32
|
ArithmeticOperation,
|
33
33
|
AmplitudeLoadingOperation,
|
34
34
|
VariableDeclarationStatement,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
|
-
from classiq.interface.ast_node import ASTNodeType,
|
3
|
+
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
4
4
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
5
5
|
|
6
6
|
if TYPE_CHECKING:
|
@@ -14,4 +14,4 @@ class WithinApply(QuantumOperation):
|
|
14
14
|
action: "StatementBlock"
|
15
15
|
|
16
16
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
17
|
-
return
|
17
|
+
return reset_lists(self, ["compute", "action"])
|