classiq 0.69.0__py3-none-any.whl → 0.70.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/analyzer/analyzer.py +0 -18
- classiq/analyzer/url_utils.py +9 -4
- classiq/applications/combinatorial_helpers/pyomo_utils.py +2 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +6 -0
- classiq/interface/chemistry/operator.py +1 -21
- classiq/interface/executor/quantum_instruction_set.py +1 -0
- classiq/interface/generator/arith/arithmetic.py +21 -6
- classiq/interface/generator/circuit_code/circuit_code.py +4 -0
- classiq/interface/generator/circuit_code/types_and_constants.py +1 -0
- classiq/interface/generator/expressions/atomic_expression_functions.py +1 -2
- classiq/interface/generator/expressions/expression_types.py +8 -2
- classiq/interface/generator/expressions/proxies/__init__.py +0 -0
- classiq/interface/generator/expressions/proxies/classical/__init__.py +0 -0
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +75 -0
- classiq/interface/generator/expressions/proxies/classical/classical_proxy.py +26 -0
- classiq/interface/generator/expressions/proxies/classical/classical_scalar_proxy.py +32 -0
- classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +31 -0
- classiq/interface/generator/expressions/proxies/quantum/__init__.py +0 -0
- classiq/interface/generator/expressions/{qmod_qarray_proxy.py → proxies/quantum/qmod_qarray_proxy.py} +3 -1
- classiq/interface/generator/expressions/{qmod_qscalar_proxy.py → proxies/quantum/qmod_qscalar_proxy.py} +3 -1
- classiq/interface/generator/expressions/{qmod_qstruct_proxy.py → proxies/quantum/qmod_qstruct_proxy.py} +3 -1
- classiq/interface/generator/functions/classical_type.py +23 -29
- classiq/interface/generator/functions/type_name.py +26 -2
- classiq/interface/generator/generated_circuit_data.py +21 -3
- classiq/interface/generator/model/preferences/preferences.py +1 -0
- classiq/interface/generator/quantum_program.py +0 -1
- classiq/interface/model/native_function_definition.py +0 -10
- classiq/interface/model/quantum_type.py +15 -3
- classiq/model_expansions/atomic_expression_functions_defs.py +9 -3
- classiq/model_expansions/evaluators/arg_type_match.py +4 -2
- classiq/model_expansions/evaluators/classical_expression.py +2 -2
- classiq/model_expansions/evaluators/control.py +1 -1
- classiq/model_expansions/evaluators/parameter_types.py +58 -16
- classiq/model_expansions/evaluators/quantum_type_utils.py +7 -57
- classiq/model_expansions/expression_evaluator.py +3 -1
- classiq/model_expansions/generative_functions.py +63 -4
- classiq/model_expansions/quantum_operations/arithmetic/__init__.py +0 -0
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +60 -0
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +9 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +0 -22
- classiq/model_expansions/scope.py +7 -6
- classiq/model_expansions/scope_initialization.py +17 -16
- classiq/model_expansions/transformers/model_renamer.py +13 -4
- classiq/model_expansions/visitors/variable_references.py +8 -4
- classiq/open_library/functions/__init__.py +2 -0
- classiq/open_library/functions/lookup_table.py +58 -0
- classiq/qmod/declaration_inferrer.py +3 -1
- classiq/qmod/qmod_parameter.py +8 -0
- classiq/qmod/qmod_variable.py +11 -14
- classiq/qmod/semantics/annotation/call_annotation.py +0 -28
- classiq/qmod/semantics/annotation/qstruct_annotator.py +21 -1
- classiq/qmod/semantics/validation/main_validation.py +1 -1
- classiq/qmod/semantics/validation/type_hints.py +29 -0
- classiq/qmod/utilities.py +38 -1
- {classiq-0.69.0.dist-info → classiq-0.70.0.dist-info}/METADATA +10 -12
- {classiq-0.69.0.dist-info → classiq-0.70.0.dist-info}/RECORD +60 -49
- {classiq-0.69.0.dist-info → classiq-0.70.0.dist-info}/WHEEL +1 -1
- /classiq/interface/generator/expressions/{qmod_struct_instance.py → proxies/classical/qmod_struct_instance.py} +0 -0
- /classiq/interface/generator/expressions/{qmod_sized_proxy.py → proxies/quantum/qmod_sized_proxy.py} +0 -0
classiq/analyzer/analyzer.py
CHANGED
@@ -5,7 +5,6 @@ import webbrowser
|
|
5
5
|
from collections.abc import Sequence
|
6
6
|
from importlib.util import find_spec
|
7
7
|
from typing import Any, Optional, Union
|
8
|
-
from urllib.parse import urljoin
|
9
8
|
|
10
9
|
import plotly.graph_objects as go
|
11
10
|
|
@@ -21,7 +20,6 @@ from classiq.analyzer.analyzer_utilities import (
|
|
21
20
|
DeviceName,
|
22
21
|
ProviderNameEnum,
|
23
22
|
)
|
24
|
-
from classiq.analyzer.url_utils import circuit_page_uri, client_ide_base_url
|
25
23
|
|
26
24
|
find_ipywidgets = find_spec("ipywidgets")
|
27
25
|
VBox = Any
|
@@ -63,22 +61,6 @@ class Analyzer(AnalyzerUtilities):
|
|
63
61
|
transpilation_option=self.circuit.model.execution_preferences.transpile_to_hardware,
|
64
62
|
)
|
65
63
|
|
66
|
-
def analyzer_app(self) -> None:
|
67
|
-
"""Opens the analyzer app with synthesis interactive results.
|
68
|
-
|
69
|
-
Returns:
|
70
|
-
None.
|
71
|
-
"""
|
72
|
-
result = async_utils.run(ApiWrapper.call_analyzer_app(self.circuit))
|
73
|
-
webbrowser.open_new_tab(
|
74
|
-
urljoin(
|
75
|
-
client_ide_base_url(),
|
76
|
-
circuit_page_uri(
|
77
|
-
circuit_id=result.id, circuit_version=self.circuit.version
|
78
|
-
),
|
79
|
-
)
|
80
|
-
)
|
81
|
-
|
82
64
|
def get_available_devices(
|
83
65
|
self, providers: Optional[list[ProviderNameEnum]] = None
|
84
66
|
) -> dict[ProviderNameEnum, list[DeviceName]]:
|
classiq/analyzer/url_utils.py
CHANGED
@@ -7,6 +7,7 @@ import classiq
|
|
7
7
|
|
8
8
|
QUERY_START_MARK = "?"
|
9
9
|
VERSION_QUERY_PARAM = "version"
|
10
|
+
LOGIN_QUERY_PARAM = "login"
|
10
11
|
|
11
12
|
|
12
13
|
def client_ide_base_url() -> str:
|
@@ -14,13 +15,17 @@ def client_ide_base_url() -> str:
|
|
14
15
|
return str(client.config.ide)
|
15
16
|
|
16
17
|
|
17
|
-
def
|
18
|
-
return
|
19
|
-
{
|
18
|
+
def circuit_page_search_params(circuit_version: str) -> str:
|
19
|
+
return urllib.parse.urlencode(
|
20
|
+
{
|
21
|
+
LOGIN_QUERY_PARAM: True,
|
22
|
+
VERSION_QUERY_PARAM: circuit_version,
|
23
|
+
}
|
20
24
|
)
|
21
25
|
|
22
26
|
|
23
27
|
def circuit_page_uri(circuit_id: str, circuit_version: str) -> str:
|
24
28
|
url = urljoin(f"{routes.ANALYZER_CIRCUIT_PAGE}/", circuit_id)
|
25
|
-
|
29
|
+
query_string = circuit_page_search_params(circuit_version)
|
30
|
+
url += QUERY_START_MARK + query_string
|
26
31
|
return url
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import copy
|
1
2
|
import math
|
2
3
|
import re
|
3
4
|
from collections import defaultdict
|
@@ -209,6 +210,7 @@ def convert_pyomo_to_global_presentation(
|
|
209
210
|
def pyomo2qmod(
|
210
211
|
struct_name: str, pyo_model: ConcreteModel
|
211
212
|
) -> CombinatorialOptimizationStructDeclaration:
|
213
|
+
pyo_model = copy.deepcopy(pyo_model)
|
212
214
|
symbols_map = PyomoSympyBimap()
|
213
215
|
|
214
216
|
variables: list[sympy.Symbol] = []
|
classiq/interface/_version.py
CHANGED
@@ -175,6 +175,12 @@ class ClassiqNvidiaBackendNames(StrEnum):
|
|
175
175
|
BRAKET_NVIDIA_SIMULATOR = "braket_nvidia_simulator"
|
176
176
|
BRAKET_NVIDIA_SIMULATOR_STATEVECTOR = "braket_nvidia_simulator_statevector"
|
177
177
|
|
178
|
+
def is_braket_nvidia_backend(self) -> bool:
|
179
|
+
return self in (
|
180
|
+
self.BRAKET_NVIDIA_SIMULATOR,
|
181
|
+
self.BRAKET_NVIDIA_SIMULATOR_STATEVECTOR,
|
182
|
+
)
|
183
|
+
|
178
184
|
|
179
185
|
class IntelBackendNames(StrEnum):
|
180
186
|
SIMULATOR = "intel_qsdk_simulator"
|
@@ -85,31 +85,11 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
85
85
|
raise ClassiqValueError("Pauli strings have incompatible lengths.")
|
86
86
|
return pauli_list
|
87
87
|
|
88
|
-
@staticmethod
|
89
|
-
def check_if_hermitian(pauli_list: PydanticPauliList) -> bool:
|
90
|
-
if all(isinstance(summand[1], (float, int, complex)) for summand in pauli_list):
|
91
|
-
if all(np.isclose(summand[1].imag, 0) for summand in pauli_list): # type: ignore[union-attr]
|
92
|
-
return True
|
93
|
-
|
94
|
-
for pauli_string, coeff in pauli_list:
|
95
|
-
reverse_string = pauli_string[::-1]
|
96
|
-
reverse_found = False
|
97
|
-
for other_string, other_coeff in pauli_list:
|
98
|
-
if other_string == reverse_string and np.isclose(
|
99
|
-
coeff, other_coeff.conjugate() # type: ignore[union-attr]
|
100
|
-
):
|
101
|
-
reverse_found = True
|
102
|
-
break
|
103
|
-
if not reverse_found:
|
104
|
-
return False
|
105
|
-
return True
|
106
|
-
return False
|
107
|
-
|
108
88
|
@pydantic.model_validator(mode="before")
|
109
89
|
@classmethod
|
110
90
|
def _validate_hermitianity(cls, values: dict[str, Any]) -> dict[str, Any]:
|
111
91
|
pauli_list = values.get("pauli_list", [])
|
112
|
-
if
|
92
|
+
if all(isinstance(summand[1], (float, int, complex)) for summand in pauli_list):
|
113
93
|
values["is_hermitian"] = all(
|
114
94
|
np.isclose(complex(summand[1]).real, summand[1])
|
115
95
|
for summand in pauli_list
|
@@ -22,6 +22,9 @@ from classiq.interface.generator.arith.arithmetic_result_builder import (
|
|
22
22
|
)
|
23
23
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
24
24
|
from classiq.interface.generator.expressions.expression import Expression
|
25
|
+
from classiq.interface.generator.expressions.expression_constants import (
|
26
|
+
BOOLEAN_LITERALS,
|
27
|
+
)
|
25
28
|
from classiq.interface.model.quantum_type import (
|
26
29
|
QuantumNumeric,
|
27
30
|
QuantumType,
|
@@ -40,6 +43,10 @@ def is_zero(expr: str) -> bool:
|
|
40
43
|
return is_constant(expr) and float(expr) == 0
|
41
44
|
|
42
45
|
|
46
|
+
def is_bool(expr: str) -> bool:
|
47
|
+
return expr in BOOLEAN_LITERALS
|
48
|
+
|
49
|
+
|
43
50
|
class Arithmetic(ArithmeticExpressionABC):
|
44
51
|
target: Optional[RegisterArithmeticInfo] = None
|
45
52
|
inputs_to_save: set[str] = pydantic.Field(default_factory=set)
|
@@ -115,7 +122,7 @@ def get_arithmetic_params(
|
|
115
122
|
def compute_arithmetic_result_type(
|
116
123
|
expr_str: str, var_types: dict[str, QuantumType], machine_precision: int
|
117
124
|
) -> QuantumNumeric:
|
118
|
-
if is_zero(expr_str):
|
125
|
+
if is_zero(expr_str) or is_bool(expr_str):
|
119
126
|
return QuantumNumeric(
|
120
127
|
size=Expression(expr="1"),
|
121
128
|
is_signed=Expression(expr="False"),
|
@@ -153,6 +160,17 @@ def aggregate_numeric_types(
|
|
153
160
|
)
|
154
161
|
|
155
162
|
|
163
|
+
def _eval_num(val: ast.AST) -> float:
|
164
|
+
if isinstance(val, ast.Num):
|
165
|
+
return cast(float, val.value)
|
166
|
+
if isinstance(val, ast.UnaryOp) and isinstance(val.op, ast.USub):
|
167
|
+
return -_eval_num(val.operand)
|
168
|
+
raise ClassiqValueError(
|
169
|
+
"Classical lists with quantum subscripts must contain compile-time classical "
|
170
|
+
"real numbers"
|
171
|
+
)
|
172
|
+
|
173
|
+
|
156
174
|
class _QuantumSubscriptRemover(ast.NodeTransformer):
|
157
175
|
def __init__(self, machine_precision: int) -> None:
|
158
176
|
self._machine_precision = machine_precision
|
@@ -161,10 +179,7 @@ class _QuantumSubscriptRemover(ast.NodeTransformer):
|
|
161
179
|
def visit_Call(self, node: ast.Call) -> ast.expr:
|
162
180
|
if not isinstance(node.func, ast.Name) or node.func.id != "Piecewise":
|
163
181
|
return node
|
164
|
-
items = [
|
165
|
-
cast(float, cast(ast.Num, cast(ast.Tuple, arg).elts[0]).value)
|
166
|
-
for arg in node.args
|
167
|
-
]
|
182
|
+
items = [_eval_num(cast(ast.Tuple, arg).elts[0]) for arg in node.args]
|
168
183
|
numeric_types = [
|
169
184
|
compute_arithmetic_result_type(str(num), {}, self._machine_precision)
|
170
185
|
for num in items
|
@@ -172,7 +187,7 @@ class _QuantumSubscriptRemover(ast.NodeTransformer):
|
|
172
187
|
unified_numeric_type = register_info_to_quantum_type(
|
173
188
|
aggregate_numeric_types(numeric_types)
|
174
189
|
)
|
175
|
-
substitution_var_name = f"
|
190
|
+
substitution_var_name = f"lut__{len(self.substitutions_types)}__"
|
176
191
|
self.substitutions_types[substitution_var_name] = unified_numeric_type
|
177
192
|
return ast.Name(id=substitution_var_name)
|
178
193
|
|
@@ -49,6 +49,10 @@ class CircuitCodeInterface(pydantic.BaseModel):
|
|
49
49
|
def qasm_cirq_compatible(self) -> Optional[Code]:
|
50
50
|
return self.outputs.get(QuantumFormat.QASM_CIRQ_COMPATIBLE)
|
51
51
|
|
52
|
+
@property
|
53
|
+
def _execution_serialization(self) -> Optional[Code]:
|
54
|
+
return self.outputs.get(QuantumFormat.EXECUTION_SERIALIZATION)
|
55
|
+
|
52
56
|
def get_code(self, instruction_set: QuantumInstructionSet) -> Code:
|
53
57
|
quantum_format: QuantumFormat = INSTRUCTION_SET_TO_FORMAT[instruction_set]
|
54
58
|
code = self.outputs.get(quantum_format)
|
@@ -12,6 +12,7 @@ INSTRUCTION_SET_TO_FORMAT: dict[QuantumInstructionSet, QuantumFormat] = {
|
|
12
12
|
QuantumInstructionSet.QASM: QuantumFormat.QASM,
|
13
13
|
QuantumInstructionSet.QSHARP: QuantumFormat.QSHARP,
|
14
14
|
QuantumInstructionSet.IONQ: QuantumFormat.IONQ,
|
15
|
+
QuantumInstructionSet.INTERNAL: QuantumFormat.EXECUTION_SERIALIZATION,
|
15
16
|
}
|
16
17
|
VENDOR_TO_INSTRUCTION_SET: dict[Provider, QuantumInstructionSet] = {
|
17
18
|
Provider.CLASSIQ: QuantumInstructionSet.QASM,
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
|
2
|
-
|
3
1
|
SUPPORTED_PYTHON_BUILTIN_FUNCTIONS = {"len", "sum", "print"}
|
4
2
|
|
5
3
|
SUPPORTED_CLASSIQ_BUILTIN_FUNCTIONS = {
|
@@ -33,6 +31,7 @@ SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS = {
|
|
33
31
|
*SUPPORTED_PYTHON_BUILTIN_FUNCTIONS,
|
34
32
|
}
|
35
33
|
|
34
|
+
CLASSICAL_ATTRIBUTES = {"len", "size", "is_signed", "fraction_digits"}
|
36
35
|
SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS_QMOD = (
|
37
36
|
SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS - CLASSICAL_ATTRIBUTES
|
38
37
|
)
|
@@ -4,10 +4,15 @@ from sympy import Expr
|
|
4
4
|
from sympy.logic.boolalg import Boolean
|
5
5
|
|
6
6
|
from classiq.interface.generator.expressions.handle_identifier import HandleIdentifier
|
7
|
-
from classiq.interface.generator.expressions.
|
8
|
-
|
7
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
8
|
+
ClassicalProxy,
|
9
|
+
)
|
10
|
+
from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
|
9
11
|
QmodStructInstance,
|
10
12
|
)
|
13
|
+
from classiq.interface.generator.expressions.proxies.quantum.qmod_sized_proxy import (
|
14
|
+
QmodSizedProxy,
|
15
|
+
)
|
11
16
|
from classiq.interface.generator.expressions.type_proxy import TypeProxy
|
12
17
|
|
13
18
|
RuntimeConstant = Union[
|
@@ -19,6 +24,7 @@ RuntimeConstant = Union[
|
|
19
24
|
QmodSizedProxy,
|
20
25
|
TypeProxy,
|
21
26
|
HandleIdentifier,
|
27
|
+
ClassicalProxy,
|
22
28
|
]
|
23
29
|
RuntimeExpression = Union[Expr, Boolean]
|
24
30
|
ExpressionValue = Union[RuntimeConstant, RuntimeExpression]
|
File without changes
|
File without changes
|
@@ -0,0 +1,75 @@
|
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import TYPE_CHECKING, Union
|
3
|
+
|
4
|
+
from sympy import Integer
|
5
|
+
|
6
|
+
from classiq.interface.exceptions import ClassiqValueError
|
7
|
+
from classiq.interface.generator.expressions.expression import Expression
|
8
|
+
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
9
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
10
|
+
ClassicalProxy,
|
11
|
+
)
|
12
|
+
from classiq.interface.model.handle_binding import (
|
13
|
+
HandleBinding,
|
14
|
+
SlicedHandleBinding,
|
15
|
+
SubscriptHandleBinding,
|
16
|
+
)
|
17
|
+
|
18
|
+
if TYPE_CHECKING:
|
19
|
+
from classiq.interface.generator.expressions.expression_types import ExpressionValue
|
20
|
+
from classiq.interface.generator.functions.concrete_types import (
|
21
|
+
ConcreteClassicalType,
|
22
|
+
)
|
23
|
+
|
24
|
+
|
25
|
+
class ClassicalArrayProxy(NonSymbolicExpr, ClassicalProxy):
|
26
|
+
def __init__(
|
27
|
+
self, handle: HandleBinding, element_type: "ConcreteClassicalType", length: int
|
28
|
+
) -> None:
|
29
|
+
super().__init__(handle)
|
30
|
+
self._element_type = element_type
|
31
|
+
self._length = length
|
32
|
+
|
33
|
+
@property
|
34
|
+
def fields(self) -> Mapping[str, "ExpressionValue"]:
|
35
|
+
return {"len": self._length}
|
36
|
+
|
37
|
+
@property
|
38
|
+
def type_name(self) -> str:
|
39
|
+
return "Array"
|
40
|
+
|
41
|
+
def __getitem__(self, key: Union[slice, int, Integer]) -> ClassicalProxy:
|
42
|
+
return (
|
43
|
+
self._get_slice(key) if isinstance(key, slice) else self._get_subscript(key)
|
44
|
+
)
|
45
|
+
|
46
|
+
def _get_slice(self, slice_: slice) -> ClassicalProxy:
|
47
|
+
start = int(slice_.start)
|
48
|
+
stop = int(slice_.stop)
|
49
|
+
if start >= stop:
|
50
|
+
raise ClassiqValueError("Array slice has non-positive length")
|
51
|
+
if start < 0 or stop > self._length:
|
52
|
+
raise ClassiqValueError("Array slice is out of bounds")
|
53
|
+
return ClassicalArrayProxy(
|
54
|
+
SlicedHandleBinding(
|
55
|
+
base_handle=self.handle,
|
56
|
+
start=Expression(expr=str(start)),
|
57
|
+
end=Expression(expr=str(stop)),
|
58
|
+
),
|
59
|
+
self._element_type,
|
60
|
+
stop - start,
|
61
|
+
)
|
62
|
+
|
63
|
+
def _get_subscript(self, index_: Union[int, Integer]) -> ClassicalProxy:
|
64
|
+
index = int(index_)
|
65
|
+
if index < 0:
|
66
|
+
raise ClassiqValueError(
|
67
|
+
"Array index is out of bounds (negative indices are not supported)"
|
68
|
+
)
|
69
|
+
if index >= self._length:
|
70
|
+
raise ClassiqValueError("Array index is out of bounds")
|
71
|
+
return self._element_type.get_classical_proxy(
|
72
|
+
SubscriptHandleBinding(
|
73
|
+
base_handle=self._handle, index=Expression(expr=str(index_))
|
74
|
+
)
|
75
|
+
)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
if TYPE_CHECKING:
|
5
|
+
from classiq.interface.generator.expressions.expression_types import ExpressionValue
|
6
|
+
from classiq.interface.model.handle_binding import HandleBinding
|
7
|
+
|
8
|
+
|
9
|
+
class ClassicalProxy:
|
10
|
+
def __init__(self, handle: "HandleBinding") -> None:
|
11
|
+
self._handle = handle
|
12
|
+
|
13
|
+
@property
|
14
|
+
def handle(self) -> "HandleBinding":
|
15
|
+
return self._handle
|
16
|
+
|
17
|
+
def __str__(self) -> str:
|
18
|
+
return str(self.handle)
|
19
|
+
|
20
|
+
@property
|
21
|
+
def fields(self) -> Mapping[str, "ExpressionValue"]:
|
22
|
+
raise NotImplementedError
|
23
|
+
|
24
|
+
@property
|
25
|
+
def type_name(self) -> str:
|
26
|
+
raise NotImplementedError
|
@@ -0,0 +1,32 @@
|
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import TYPE_CHECKING, Any
|
3
|
+
|
4
|
+
from sympy import Symbol
|
5
|
+
|
6
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
7
|
+
ClassicalProxy,
|
8
|
+
)
|
9
|
+
from classiq.interface.model.handle_binding import HandleBinding
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from classiq.interface.generator.expressions.expression_types import ExpressionValue
|
13
|
+
from classiq.interface.generator.functions.classical_type import ClassicalType
|
14
|
+
|
15
|
+
|
16
|
+
class ClassicalScalarProxy(Symbol, ClassicalProxy):
|
17
|
+
def __new__(
|
18
|
+
cls, handle: HandleBinding, *args: Any, **assumptions: bool
|
19
|
+
) -> "ClassicalScalarProxy":
|
20
|
+
return super().__new__(cls, str(handle), **assumptions)
|
21
|
+
|
22
|
+
def __init__(self, handle: HandleBinding, classical_type: "ClassicalType") -> None:
|
23
|
+
super().__init__(handle)
|
24
|
+
self._classical_type = classical_type
|
25
|
+
|
26
|
+
@property
|
27
|
+
def fields(self) -> Mapping[str, "ExpressionValue"]:
|
28
|
+
return {}
|
29
|
+
|
30
|
+
@property
|
31
|
+
def type_name(self) -> str:
|
32
|
+
return type(self._classical_type).__name__
|
@@ -0,0 +1,31 @@
|
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
5
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
6
|
+
ClassicalProxy,
|
7
|
+
)
|
8
|
+
from classiq.interface.model.handle_binding import FieldHandleBinding, HandleBinding
|
9
|
+
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
from classiq.interface.generator.expressions.expression_types import ExpressionValue
|
12
|
+
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
13
|
+
|
14
|
+
|
15
|
+
class ClassicalStructProxy(NonSymbolicExpr, ClassicalProxy):
|
16
|
+
def __init__(self, handle: HandleBinding, decl: "StructDeclaration") -> None:
|
17
|
+
super().__init__(handle)
|
18
|
+
self._decl = decl
|
19
|
+
|
20
|
+
@property
|
21
|
+
def fields(self) -> Mapping[str, "ExpressionValue"]:
|
22
|
+
return {
|
23
|
+
field_name: field_type.get_classical_proxy(
|
24
|
+
FieldHandleBinding(base_handle=self.handle, field_name=field_name)
|
25
|
+
)
|
26
|
+
for field_name, field_type in self._decl.variables.items()
|
27
|
+
}
|
28
|
+
|
29
|
+
@property
|
30
|
+
def type_name(self) -> str:
|
31
|
+
return f"Struct {self._decl.name}"
|
File without changes
|
@@ -6,7 +6,9 @@ from sympy import Integer
|
|
6
6
|
from classiq.interface.exceptions import ClassiqValueError
|
7
7
|
from classiq.interface.generator.expressions.expression import Expression
|
8
8
|
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
9
|
-
from classiq.interface.generator.expressions.qmod_sized_proxy import
|
9
|
+
from classiq.interface.generator.expressions.proxies.quantum.qmod_sized_proxy import (
|
10
|
+
QmodSizedProxy,
|
11
|
+
)
|
10
12
|
from classiq.interface.model.handle_binding import (
|
11
13
|
HandleBinding,
|
12
14
|
SlicedHandleBinding,
|
@@ -4,7 +4,9 @@ from typing import Any
|
|
4
4
|
from sympy import Symbol
|
5
5
|
|
6
6
|
from classiq.interface.exceptions import ClassiqValueError
|
7
|
-
from classiq.interface.generator.expressions.qmod_sized_proxy import
|
7
|
+
from classiq.interface.generator.expressions.proxies.quantum.qmod_sized_proxy import (
|
8
|
+
QmodSizedProxy,
|
9
|
+
)
|
8
10
|
from classiq.interface.model.handle_binding import HandleBinding
|
9
11
|
|
10
12
|
|
@@ -2,7 +2,9 @@ from collections.abc import Mapping
|
|
2
2
|
from typing import TYPE_CHECKING
|
3
3
|
|
4
4
|
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
5
|
-
from classiq.interface.generator.expressions.qmod_sized_proxy import
|
5
|
+
from classiq.interface.generator.expressions.proxies.quantum.qmod_sized_proxy import (
|
6
|
+
QmodSizedProxy,
|
7
|
+
)
|
6
8
|
from classiq.interface.model.handle_binding import (
|
7
9
|
FieldHandleBinding,
|
8
10
|
HandleBinding,
|
@@ -1,30 +1,31 @@
|
|
1
|
-
from typing import TYPE_CHECKING, Any, Literal
|
1
|
+
from typing import TYPE_CHECKING, Any, Literal
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
from pydantic import ConfigDict, PrivateAttr
|
5
|
-
from sympy import IndexedBase, Symbol
|
6
5
|
from typing_extensions import Self
|
7
6
|
|
8
7
|
from classiq.interface.ast_node import HashableASTNode
|
9
|
-
from classiq.interface.generator.expressions.
|
8
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_array_proxy import (
|
9
|
+
ClassicalArrayProxy,
|
10
|
+
)
|
11
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
12
|
+
ClassicalProxy,
|
13
|
+
)
|
14
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_scalar_proxy import (
|
15
|
+
ClassicalScalarProxy,
|
16
|
+
)
|
10
17
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
18
|
+
from classiq.interface.model.handle_binding import HandleBinding
|
11
19
|
|
12
20
|
if TYPE_CHECKING:
|
13
21
|
from classiq.interface.generator.functions.concrete_types import (
|
14
22
|
ConcreteClassicalType,
|
15
23
|
)
|
16
24
|
|
17
|
-
CLASSICAL_ATTRIBUTES = {"len", "size", "is_signed", "fraction_digits"}
|
18
|
-
|
19
|
-
NamedSymbol = Union[IndexedBase, Symbol]
|
20
|
-
|
21
25
|
|
22
26
|
class ClassicalType(HashableASTNode):
|
23
27
|
_is_generative: bool = PrivateAttr(default=False)
|
24
28
|
|
25
|
-
def as_symbolic(self, name: str) -> Union[NamedSymbol, list[NamedSymbol]]:
|
26
|
-
return Symbol(name)
|
27
|
-
|
28
29
|
model_config = ConfigDict(extra="forbid")
|
29
30
|
|
30
31
|
def __str__(self) -> str:
|
@@ -38,13 +39,13 @@ class ClassicalType(HashableASTNode):
|
|
38
39
|
def is_generative(self) -> bool:
|
39
40
|
return self._is_generative
|
40
41
|
|
42
|
+
def get_classical_proxy(self, handle: HandleBinding) -> ClassicalProxy:
|
43
|
+
return ClassicalScalarProxy(handle, self)
|
44
|
+
|
41
45
|
|
42
46
|
class Integer(ClassicalType):
|
43
47
|
kind: Literal["int"]
|
44
48
|
|
45
|
-
def as_symbolic(self, name: str) -> Symbol:
|
46
|
-
return Symbol(name, integer=True)
|
47
|
-
|
48
49
|
@pydantic.model_validator(mode="before")
|
49
50
|
@classmethod
|
50
51
|
def _set_kind(cls, values: Any) -> dict[str, Any]:
|
@@ -54,9 +55,6 @@ class Integer(ClassicalType):
|
|
54
55
|
class Real(ClassicalType):
|
55
56
|
kind: Literal["real"]
|
56
57
|
|
57
|
-
def as_symbolic(self, name: str) -> Symbol:
|
58
|
-
return Symbol(name, real=True)
|
59
|
-
|
60
58
|
@pydantic.model_validator(mode="before")
|
61
59
|
@classmethod
|
62
60
|
def _set_kind(cls, values: Any) -> dict[str, Any]:
|
@@ -76,14 +74,14 @@ class ClassicalList(ClassicalType):
|
|
76
74
|
kind: Literal["list"]
|
77
75
|
element_type: "ConcreteClassicalType"
|
78
76
|
|
79
|
-
def as_symbolic(self, name: str) -> Symbol:
|
80
|
-
return IndexedBase(name)
|
81
|
-
|
82
77
|
@pydantic.model_validator(mode="before")
|
83
78
|
@classmethod
|
84
79
|
def _set_kind(cls, values: Any) -> dict[str, Any]:
|
85
80
|
return values_with_discriminator(values, "kind", "list")
|
86
81
|
|
82
|
+
def get_classical_proxy(self, handle: HandleBinding) -> ClassicalProxy:
|
83
|
+
raise NotImplementedError
|
84
|
+
|
87
85
|
|
88
86
|
class StructMetaType(ClassicalType):
|
89
87
|
kind: Literal["type_proxy"]
|
@@ -93,20 +91,23 @@ class StructMetaType(ClassicalType):
|
|
93
91
|
def _set_kind(cls, values: Any) -> dict[str, Any]:
|
94
92
|
return values_with_discriminator(values, "kind", "type_proxy")
|
95
93
|
|
94
|
+
def get_classical_proxy(self, handle: HandleBinding) -> ClassicalProxy:
|
95
|
+
raise NotImplementedError
|
96
|
+
|
96
97
|
|
97
98
|
class ClassicalArray(ClassicalType):
|
98
99
|
kind: Literal["array"]
|
99
100
|
element_type: "ConcreteClassicalType"
|
100
101
|
size: pydantic.PositiveInt
|
101
102
|
|
102
|
-
def as_symbolic(self, name: str) -> list:
|
103
|
-
return [self.element_type.as_symbolic(f"{name}_{i}") for i in range(self.size)]
|
104
|
-
|
105
103
|
@pydantic.model_validator(mode="before")
|
106
104
|
@classmethod
|
107
105
|
def _set_kind(cls, values: Any) -> dict[str, Any]:
|
108
106
|
return values_with_discriminator(values, "kind", "array")
|
109
107
|
|
108
|
+
def get_classical_proxy(self, handle: HandleBinding) -> ClassicalProxy:
|
109
|
+
return ClassicalArrayProxy(handle, self.element_type, self.size)
|
110
|
+
|
110
111
|
|
111
112
|
class OpaqueHandle(ClassicalType):
|
112
113
|
pass
|
@@ -148,12 +149,5 @@ class IQAERes(OpaqueHandle):
|
|
148
149
|
return values_with_discriminator(values, "kind", "iqae_result")
|
149
150
|
|
150
151
|
|
151
|
-
def as_symbolic(symbols: dict[str, ClassicalType]) -> dict[str, RuntimeExpression]:
|
152
|
-
return {
|
153
|
-
param_name: param_type.as_symbolic(param_name)
|
154
|
-
for param_name, param_type in symbols.items()
|
155
|
-
}
|
156
|
-
|
157
|
-
|
158
152
|
class QmodPyObject:
|
159
153
|
pass
|