classiq 0.83.0__py3-none-any.whl → 0.84.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 +27 -0
- classiq/applications/chemistry/chemistry_model_constructor.py +0 -2
- classiq/applications/chemistry/hartree_fock.py +68 -0
- classiq/applications/chemistry/mapping.py +85 -0
- classiq/applications/chemistry/op_utils.py +79 -0
- classiq/applications/chemistry/problems.py +195 -0
- classiq/applications/chemistry/ucc.py +109 -0
- classiq/applications/chemistry/z2_symmetries.py +368 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +30 -1
- classiq/{model_expansions/evaluators → evaluators}/arg_type_match.py +12 -4
- classiq/{model_expansions/evaluators → evaluators}/argument_types.py +1 -1
- classiq/{model_expansions/evaluators → evaluators}/classical_expression.py +1 -1
- classiq/{model_expansions/evaluators → evaluators}/classical_type_inference.py +3 -4
- classiq/{model_expansions/evaluators → evaluators}/parameter_types.py +17 -15
- classiq/execution/__init__.py +12 -1
- classiq/execution/execution_session.py +189 -43
- classiq/execution/jobs.py +26 -1
- classiq/execution/qnn.py +2 -2
- classiq/execution/user_budgets.py +39 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/constants.py +1 -0
- classiq/interface/execution/primitives.py +29 -1
- classiq/interface/executor/estimate_cost.py +35 -0
- classiq/interface/executor/execution_result.py +13 -0
- classiq/interface/executor/result.py +116 -1
- classiq/interface/executor/user_budget.py +26 -33
- classiq/interface/generator/expressions/atomic_expression_functions.py +5 -1
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -6
- classiq/interface/generator/functions/classical_type.py +2 -35
- classiq/interface/generator/functions/concrete_types.py +0 -3
- classiq/interface/generator/functions/type_modifier.py +0 -19
- classiq/interface/generator/generated_circuit_data.py +0 -8
- classiq/interface/generator/types/compilation_metadata.py +0 -3
- classiq/interface/ide/visual_model.py +6 -2
- classiq/interface/model/model.py +12 -7
- classiq/interface/model/port_declaration.py +2 -24
- classiq/interface/pretty_print/__init__.py +0 -0
- classiq/{qmod/native → interface/pretty_print}/expression_to_qmod.py +18 -11
- classiq/interface/server/routes.py +4 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +42 -5
- classiq/model_expansions/interpreters/base_interpreter.py +3 -3
- classiq/model_expansions/quantum_operations/allocate.py +1 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +1 -1
- classiq/model_expansions/quantum_operations/bind.py +2 -2
- classiq/model_expansions/quantum_operations/call_emitter.py +26 -20
- classiq/model_expansions/quantum_operations/variable_decleration.py +1 -1
- classiq/model_expansions/scope_initialization.py +3 -3
- classiq/model_expansions/transformers/model_renamer.py +6 -4
- classiq/model_expansions/transformers/type_modifier_inference.py +81 -43
- classiq/model_expansions/visitors/symbolic_param_inference.py +2 -3
- classiq/open_library/functions/__init__.py +3 -0
- classiq/open_library/functions/amplitude_amplification.py +10 -18
- classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
- classiq/open_library/functions/grover.py +14 -6
- classiq/open_library/functions/modular_exponentiation.py +22 -20
- classiq/open_library/functions/state_preparation.py +17 -0
- classiq/qmod/builtins/enums.py +23 -0
- classiq/qmod/builtins/functions/__init__.py +2 -0
- classiq/qmod/builtins/functions/exponentiation.py +32 -4
- classiq/qmod/builtins/structs.py +55 -3
- classiq/qmod/declaration_inferrer.py +3 -2
- classiq/qmod/native/pretty_printer.py +2 -6
- classiq/qmod/pretty_print/expression_to_python.py +2 -1
- classiq/qmod/pretty_print/pretty_printer.py +1 -6
- classiq/qmod/python_classical_type.py +12 -5
- classiq/qmod/qmod_constant.py +2 -5
- classiq/qmod/qmod_parameter.py +2 -5
- classiq/qmod/qmod_variable.py +56 -15
- classiq/qmod/quantum_expandable.py +4 -2
- classiq/qmod/quantum_function.py +7 -2
- classiq/qmod/semantics/annotation/qstruct_annotator.py +1 -1
- classiq/qmod/semantics/validation/main_validation.py +1 -9
- classiq/qmod/utilities.py +0 -2
- classiq/qmod/write_qmod.py +1 -1
- {classiq-0.83.0.dist-info → classiq-0.84.0.dist-info}/METADATA +4 -1
- {classiq-0.83.0.dist-info → classiq-0.84.0.dist-info}/RECORD +82 -73
- /classiq/{model_expansions/evaluators → evaluators}/__init__.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/control.py +0 -0
- /classiq/{model_expansions → evaluators}/expression_evaluator.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/quantum_type_utils.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/type_type_match.py +0 -0
- {classiq-0.83.0.dist-info → classiq-0.84.0.dist-info}/WHEEL +0 -0
@@ -1,9 +1,9 @@
|
|
1
1
|
import datetime
|
2
|
-
from collections import defaultdict
|
3
2
|
from typing import Optional
|
4
3
|
|
5
4
|
import pydantic
|
6
5
|
from pydantic import ConfigDict, Field
|
6
|
+
from tabulate import tabulate
|
7
7
|
|
8
8
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
9
9
|
|
@@ -15,6 +15,7 @@ class UserBudget(VersionedModel):
|
|
15
15
|
available_budget: float
|
16
16
|
used_budget: float
|
17
17
|
last_allocation_date: datetime.datetime
|
18
|
+
budget_limit: Optional[float] = Field(default=None)
|
18
19
|
|
19
20
|
model_config = ConfigDict(extra="ignore")
|
20
21
|
|
@@ -22,35 +23,27 @@ class UserBudget(VersionedModel):
|
|
22
23
|
class UserBudgets(VersionedModel):
|
23
24
|
budgets: list[UserBudget] = pydantic.Field(default=[])
|
24
25
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
for provider, values in table_data.items():
|
50
|
-
print( # noqa: T201
|
51
|
-
format_row(
|
52
|
-
provider, values["available"], values["used"], values["currency"]
|
53
|
-
)
|
54
|
-
)
|
55
|
-
|
56
|
-
print(line) # noqa: T201
|
26
|
+
def __str__(self) -> str:
|
27
|
+
rows = [
|
28
|
+
[
|
29
|
+
budget.provider,
|
30
|
+
f"{budget.used_budget:.3f}",
|
31
|
+
f"{budget.available_budget:.3f}",
|
32
|
+
(
|
33
|
+
f"{budget.budget_limit:.3f}"
|
34
|
+
if budget.budget_limit is not None
|
35
|
+
else "NOT SET"
|
36
|
+
),
|
37
|
+
budget.currency_code,
|
38
|
+
]
|
39
|
+
for budget in self.budgets
|
40
|
+
]
|
41
|
+
|
42
|
+
headers = [
|
43
|
+
"Provider",
|
44
|
+
"Used Budget",
|
45
|
+
"Remaining Budget",
|
46
|
+
"Budget Limit",
|
47
|
+
"Currency",
|
48
|
+
]
|
49
|
+
return tabulate(rows, headers=headers, tablefmt="grid")
|
@@ -23,7 +23,6 @@ CLASSIQ_EXPR_FUNCTIONS = {
|
|
23
23
|
SUPPORTED_CLASSIQ_BUILTIN_FUNCTIONS = {
|
24
24
|
*CLASSIQ_BUILTIN_CLASSICAL_FUNCTIONS,
|
25
25
|
*CLASSIQ_EXPR_FUNCTIONS,
|
26
|
-
"mod_inverse",
|
27
26
|
}
|
28
27
|
|
29
28
|
SUPPORTED_CLASSIQ_SYMPY_WRAPPERS = {
|
@@ -34,6 +33,11 @@ SUPPORTED_CLASSIQ_SYMPY_WRAPPERS = {
|
|
34
33
|
"LogicalXor",
|
35
34
|
"RShift",
|
36
35
|
"LShift",
|
36
|
+
"mod_inverse",
|
37
|
+
"min",
|
38
|
+
"Min",
|
39
|
+
"max",
|
40
|
+
"Max",
|
37
41
|
}
|
38
42
|
|
39
43
|
SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS = {
|
@@ -21,12 +21,6 @@ def subscript_to_str(index: Any) -> str:
|
|
21
21
|
|
22
22
|
|
23
23
|
class AnyClassicalValue(sympy.Symbol):
|
24
|
-
|
25
|
-
is_commutative = None
|
26
|
-
is_infinite = None
|
27
|
-
is_finite = None
|
28
|
-
is_extended_real = None
|
29
|
-
|
30
24
|
def __getitem__(self, item: Any) -> "AnyClassicalValue":
|
31
25
|
if isinstance(item, slice):
|
32
26
|
return AnyClassicalValue(f"{self}[{subscript_to_str(item)}]")
|
@@ -98,39 +98,6 @@ class Bool(ClassicalType):
|
|
98
98
|
return values_with_discriminator(values, "kind", "bool")
|
99
99
|
|
100
100
|
|
101
|
-
class ClassicalList(ClassicalType):
|
102
|
-
kind: Literal["list"]
|
103
|
-
element_type: "ConcreteClassicalType"
|
104
|
-
|
105
|
-
@pydantic.model_validator(mode="before")
|
106
|
-
@classmethod
|
107
|
-
def _set_kind(cls, values: Any) -> dict[str, Any]:
|
108
|
-
return values_with_discriminator(values, "kind", "list")
|
109
|
-
|
110
|
-
def get_classical_proxy(self, handle: HandleBinding) -> ClassicalProxy:
|
111
|
-
return ClassicalArrayProxy(
|
112
|
-
handle, self.element_type, AnyClassicalValue(f"get_field({handle}, 'len')")
|
113
|
-
)
|
114
|
-
|
115
|
-
@property
|
116
|
-
def expressions(self) -> list[Expression]:
|
117
|
-
return self.element_type.expressions
|
118
|
-
|
119
|
-
@property
|
120
|
-
def is_purely_declarative(self) -> bool:
|
121
|
-
return super().is_purely_declarative and self.element_type.is_purely_declarative
|
122
|
-
|
123
|
-
@property
|
124
|
-
def is_purely_generative(self) -> bool:
|
125
|
-
return super().is_purely_generative and self.element_type.is_purely_generative
|
126
|
-
|
127
|
-
def get_raw_type(self) -> "ConcreteClassicalType":
|
128
|
-
raw_type = ClassicalArray(element_type=self.element_type.get_raw_type())
|
129
|
-
if self._is_generative:
|
130
|
-
raw_type.set_generative()
|
131
|
-
return raw_type
|
132
|
-
|
133
|
-
|
134
101
|
class StructMetaType(ClassicalType):
|
135
102
|
kind: Literal["type_proxy"]
|
136
103
|
|
@@ -146,8 +113,8 @@ class StructMetaType(ClassicalType):
|
|
146
113
|
class ClassicalArray(ClassicalType):
|
147
114
|
kind: Literal["array"]
|
148
115
|
element_type: "ConcreteClassicalType"
|
149
|
-
size: Optional[int] = None
|
150
|
-
length: Optional[Expression] =
|
116
|
+
size: Optional[int] = pydantic.Field(exclude=True, default=None)
|
117
|
+
length: Optional[Expression] = None
|
151
118
|
|
152
119
|
@pydantic.model_validator(mode="before")
|
153
120
|
@classmethod
|
@@ -5,7 +5,6 @@ from pydantic import Field
|
|
5
5
|
from classiq.interface.generator.functions.classical_type import (
|
6
6
|
Bool,
|
7
7
|
ClassicalArray,
|
8
|
-
ClassicalList,
|
9
8
|
ClassicalTuple,
|
10
9
|
Estimation,
|
11
10
|
Histogram,
|
@@ -29,7 +28,6 @@ ConcreteClassicalType = Annotated[
|
|
29
28
|
Integer,
|
30
29
|
Real,
|
31
30
|
Bool,
|
32
|
-
ClassicalList,
|
33
31
|
StructMetaType,
|
34
32
|
TypeName,
|
35
33
|
ClassicalArray,
|
@@ -41,7 +39,6 @@ ConcreteClassicalType = Annotated[
|
|
41
39
|
],
|
42
40
|
Field(discriminator="kind"),
|
43
41
|
]
|
44
|
-
ClassicalList.model_rebuild()
|
45
42
|
ClassicalArray.model_rebuild()
|
46
43
|
ClassicalTuple.model_rebuild()
|
47
44
|
|
@@ -2,25 +2,6 @@ from classiq.interface.enum_utils import StrEnum
|
|
2
2
|
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
3
3
|
|
4
4
|
|
5
|
-
class TypeQualifier(StrEnum):
|
6
|
-
Const = "const"
|
7
|
-
QFree = "qfree"
|
8
|
-
Quantum = "quantum"
|
9
|
-
Inferred = "inferred"
|
10
|
-
|
11
|
-
def to_modifier(self) -> "TypeModifier":
|
12
|
-
if self is TypeQualifier.Const:
|
13
|
-
return TypeModifier.Const
|
14
|
-
elif self is TypeQualifier.QFree:
|
15
|
-
return TypeModifier.Permutable
|
16
|
-
elif self is TypeQualifier.Quantum:
|
17
|
-
return TypeModifier.Mutable
|
18
|
-
elif self is TypeQualifier.Inferred:
|
19
|
-
return TypeModifier.Inferred
|
20
|
-
else:
|
21
|
-
raise ClassiqInternalExpansionError(f"Unexpected type qualifier: {self}")
|
22
|
-
|
23
|
-
|
24
5
|
class TypeModifier(StrEnum):
|
25
6
|
Const = "const"
|
26
7
|
Permutable = "permutable"
|
@@ -28,8 +28,6 @@ from classiq.interface.model.statement_block import (
|
|
28
28
|
)
|
29
29
|
|
30
30
|
from classiq.model_expansions.capturing.mangling_utils import (
|
31
|
-
demangle_capture_name,
|
32
|
-
demangle_name,
|
33
31
|
is_captured_var_name,
|
34
32
|
)
|
35
33
|
|
@@ -85,12 +83,6 @@ class GeneratedRegister(pydantic.BaseModel):
|
|
85
83
|
def is_captured(self) -> bool:
|
86
84
|
return is_captured_var_name(self.name)
|
87
85
|
|
88
|
-
@staticmethod
|
89
|
-
def demangle_name(name: str) -> str:
|
90
|
-
if is_captured_var_name(name):
|
91
|
-
name = demangle_capture_name(name)
|
92
|
-
return demangle_name(name)
|
93
|
-
|
94
86
|
|
95
87
|
class GeneratedFunction(pydantic.BaseModel):
|
96
88
|
name: str
|
@@ -6,9 +6,6 @@ class CompilationMetadata(BaseModel):
|
|
6
6
|
occurrences_number: NonNegativeInt = Field(default=1)
|
7
7
|
_occupation_number: NonNegativeInt = PrivateAttr(default=0)
|
8
8
|
unchecked: list[str] = Field(default_factory=list)
|
9
|
-
atomic_qualifiers: list[str] = Field(
|
10
|
-
default_factory=list, exclude=True
|
11
|
-
) # TODO remove after deprecation https://classiq.atlassian.net/browse/CLS-2671
|
12
9
|
|
13
10
|
@property
|
14
11
|
def occupation_number(self) -> NonNegativeInt:
|
@@ -110,7 +110,9 @@ class Operation(pydantic.BaseModel):
|
|
110
110
|
name: str
|
111
111
|
qasm_name: str = pydantic.Field(default="")
|
112
112
|
details: str = pydantic.Field(default="")
|
113
|
-
children: list["Operation"]
|
113
|
+
children: list["Operation"] = pydantic.Field(default_factory=list)
|
114
|
+
# children_ids is optional in order to support backwards compatibility.
|
115
|
+
children_ids: list[int] = pydantic.Field(default_factory=list)
|
114
116
|
operation_data: Optional[OperationData] = None
|
115
117
|
operation_links: OperationLinks
|
116
118
|
control_qubits: tuple[int, ...] = pydantic.Field(default_factory=tuple)
|
@@ -129,5 +131,7 @@ class Operation(pydantic.BaseModel):
|
|
129
131
|
|
130
132
|
|
131
133
|
class ProgramVisualModel(VersionedModel):
|
132
|
-
main_operation: Operation
|
134
|
+
main_operation: Operation = pydantic.Field(default=None)
|
135
|
+
id_to_operations: dict[int, Operation] = pydantic.Field(default_factory=dict)
|
136
|
+
main_operation_id: int = pydantic.Field(default=None)
|
133
137
|
program_data: ProgramData
|
classiq/interface/model/model.py
CHANGED
@@ -185,11 +185,16 @@ class Model(VersionedModel, ASTNode):
|
|
185
185
|
return constants
|
186
186
|
|
187
187
|
def dump_no_metadata(self) -> dict[str, Any]:
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
188
|
+
compilation_metadata_with_unchecked = {
|
189
|
+
name: CompilationMetadata(unchecked=comp_metadata.unchecked)
|
190
|
+
for name, comp_metadata in self.functions_compilation_metadata.items()
|
191
|
+
if len(comp_metadata.unchecked) > 0
|
192
|
+
}
|
193
|
+
model = self.model_copy(
|
194
|
+
update={
|
195
|
+
"functions_compilation_metadata": compilation_metadata_with_unchecked,
|
196
|
+
}
|
197
|
+
)
|
198
|
+
return model.model_dump(
|
199
|
+
exclude={"constraints", "execution_preferences", "preferences"},
|
195
200
|
)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any, Literal
|
1
|
+
from typing import Any, Literal
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
from pydantic_core.core_schema import ValidationInfo
|
@@ -10,7 +10,6 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
10
10
|
)
|
11
11
|
from classiq.interface.generator.functions.type_modifier import (
|
12
12
|
TypeModifier,
|
13
|
-
TypeQualifier,
|
14
13
|
)
|
15
14
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
16
15
|
from classiq.interface.model.parameter import Parameter
|
@@ -19,35 +18,14 @@ from classiq.interface.model.parameter import Parameter
|
|
19
18
|
class AnonPortDeclaration(Parameter):
|
20
19
|
quantum_type: ConcreteQuantumType
|
21
20
|
direction: PortDeclarationDirection
|
22
|
-
type_qualifier: Optional[TypeQualifier] = pydantic.Field(
|
23
|
-
default=None, exclude=True
|
24
|
-
) # TODO remove after BWC breaking release https://classiq.atlassian.net/browse/CLS-2777
|
25
21
|
kind: Literal["PortDeclaration"]
|
26
|
-
type_modifier: TypeModifier
|
22
|
+
type_modifier: TypeModifier
|
27
23
|
|
28
24
|
@pydantic.model_validator(mode="before")
|
29
25
|
@classmethod
|
30
26
|
def _set_kind(cls, values: Any) -> dict[str, Any]:
|
31
27
|
return values_with_discriminator(values, "kind", "PortDeclaration")
|
32
28
|
|
33
|
-
@pydantic.model_validator(mode="before")
|
34
|
-
@classmethod
|
35
|
-
def _set_type_modifier(cls, values: Any) -> dict[str, Any]:
|
36
|
-
if values.get("type_modifier") is None:
|
37
|
-
type_qualifier = values.get("type_qualifier")
|
38
|
-
if type_qualifier is not None:
|
39
|
-
if isinstance(type_qualifier, TypeQualifier):
|
40
|
-
values["type_modifier"] = type_qualifier.to_modifier()
|
41
|
-
elif isinstance(type_qualifier, str):
|
42
|
-
values["type_modifier"] = TypeQualifier(
|
43
|
-
type_qualifier
|
44
|
-
).to_modifier()
|
45
|
-
else:
|
46
|
-
raise pydantic.ValidationError("Missing a type modifier")
|
47
|
-
else:
|
48
|
-
raise pydantic.ValidationError("Missing a type modifier")
|
49
|
-
return values
|
50
|
-
|
51
29
|
@pydantic.field_validator("direction", mode="before")
|
52
30
|
@classmethod
|
53
31
|
def _direction_validator(
|
File without changes
|
@@ -6,7 +6,7 @@ from typing import Callable, Optional
|
|
6
6
|
|
7
7
|
import numpy as np
|
8
8
|
|
9
|
-
from classiq.
|
9
|
+
from classiq.interface.constants import DEFAULT_DECIMAL_PRECISION
|
10
10
|
|
11
11
|
IDENTIFIER = re.compile(r"[a-zA-Z_]\w*")
|
12
12
|
BINARY_OPS: Mapping[type[ast.operator], str] = {
|
@@ -40,6 +40,10 @@ COMPARE_OPS: Mapping[type[ast.cmpop], str] = {
|
|
40
40
|
LIST_FORMAT_CHAR_LIMIT = 20
|
41
41
|
|
42
42
|
|
43
|
+
class PrettyPrinterError(AssertionError):
|
44
|
+
pass
|
45
|
+
|
46
|
+
|
43
47
|
@dataclass
|
44
48
|
class ASTToQMODCode:
|
45
49
|
level: int
|
@@ -59,10 +63,13 @@ class ASTToQMODCode:
|
|
59
63
|
elif isinstance(node, ast.Attribute):
|
60
64
|
# Enum attribute access
|
61
65
|
if not isinstance(node.value, ast.Name) or not isinstance(node.attr, str):
|
62
|
-
raise
|
66
|
+
raise PrettyPrinterError("Error parsing enum attribute access")
|
63
67
|
if not (IDENTIFIER.match(node.value.id) and IDENTIFIER.match(node.attr)):
|
64
|
-
raise
|
65
|
-
|
68
|
+
raise PrettyPrinterError("Error parsing enum attribute access")
|
69
|
+
# FIXME: identify enum member accesses by type name (CLS-2858)
|
70
|
+
if len(node.value.id) > 0 and node.value.id[0].isupper():
|
71
|
+
return f"{node.value.id!s}::{node.attr!s}"
|
72
|
+
return f"{node.value.id!s}.{node.attr!s}"
|
66
73
|
elif isinstance(node, ast.Name):
|
67
74
|
return node.id
|
68
75
|
elif isinstance(node, ast.Num):
|
@@ -91,7 +98,7 @@ class ASTToQMODCode:
|
|
91
98
|
)
|
92
99
|
elif isinstance(node, ast.Compare):
|
93
100
|
if len(node.ops) != 1 or len(node.comparators) != 1:
|
94
|
-
raise
|
101
|
+
raise PrettyPrinterError("Error parsing comparison expression.")
|
95
102
|
return "({} {} {})".format(
|
96
103
|
self.ast_to_code(node.left),
|
97
104
|
COMPARE_OPS[type(node.ops[0])],
|
@@ -108,20 +115,20 @@ class ASTToQMODCode:
|
|
108
115
|
elif isinstance(node, ast.Slice):
|
109
116
|
# A QMOD expression does not support slice step
|
110
117
|
if node.lower is None or node.upper is None or node.step is not None:
|
111
|
-
raise
|
118
|
+
raise PrettyPrinterError("Error parsing slice expression.")
|
112
119
|
return f"{self.ast_to_code(node.lower)}:{self.ast_to_code(node.upper)}"
|
113
120
|
elif isinstance(node, ast.Call):
|
114
121
|
func = self.ast_to_code(node.func)
|
115
122
|
if func == "get_field":
|
116
123
|
if len(node.args) != 2:
|
117
|
-
raise
|
124
|
+
raise PrettyPrinterError("Error parsing struct field access.")
|
118
125
|
field = str(self.ast_to_code(node.args[1])).replace("'", "")
|
119
126
|
if not IDENTIFIER.match(field):
|
120
|
-
raise
|
127
|
+
raise PrettyPrinterError("Error parsing struct field access.")
|
121
128
|
return f"{self.ast_to_code(node.args[0])}.{field}"
|
122
129
|
elif func == "struct_literal":
|
123
130
|
if len(node.args) != 1 or not isinstance(node.args[0], ast.Name):
|
124
|
-
raise
|
131
|
+
raise PrettyPrinterError("Error parsing struct literal.")
|
125
132
|
keywords = node.keywords
|
126
133
|
initializer_list = self.indent_items(
|
127
134
|
lambda: [
|
@@ -133,7 +140,7 @@ class ASTToQMODCode:
|
|
133
140
|
return f"{self.ast_to_code(node.args[0])} {{{initializer_list}}}"
|
134
141
|
elif func == "do_subscript":
|
135
142
|
if len(node.args) != 2:
|
136
|
-
raise
|
143
|
+
raise PrettyPrinterError("Error parsing array access.")
|
137
144
|
return f"{self.ast_to_code(node.args[0])}[{self.ast_to_code(node.args[1])}]"
|
138
145
|
else:
|
139
146
|
return "{}({})".format(
|
@@ -142,7 +149,7 @@ class ASTToQMODCode:
|
|
142
149
|
elif isinstance(node, ast.Expr):
|
143
150
|
return self._cleaned_ast_to_code(node.value)
|
144
151
|
else:
|
145
|
-
raise
|
152
|
+
raise PrettyPrinterError("Error parsing expression: unsupported AST node.")
|
146
153
|
|
147
154
|
def indent_items(self, items: Callable[[], list[str]]) -> str:
|
148
155
|
should_indent = (
|
@@ -91,3 +91,7 @@ IQCC_LIST_AUTH_TARGETS_FULL_PATH = IQCC_PREFIX + IQCC_LIST_AUTH_TARGETS_SUFFIX
|
|
91
91
|
|
92
92
|
USER_BUDGETS_SUFFIX = "/all"
|
93
93
|
USER_BUDGETS_FULL_PATH = USER_BUDGETS_PREFIX + USER_BUDGETS_SUFFIX
|
94
|
+
USER_BUDGET_SET_LIMIT_SUFFIX = "/set_limit"
|
95
|
+
USER_BUDGET_SET_LIMIT_FULL_PATH = USER_BUDGETS_PREFIX + USER_BUDGET_SET_LIMIT_SUFFIX
|
96
|
+
USER_BUDGET_CLEAR_LIMIT_SUFFIX = "/clear_limit"
|
97
|
+
USER_BUDGET_CLEAR_LIMIT_FULL_PATH = USER_BUDGETS_PREFIX + USER_BUDGET_CLEAR_LIMIT_SUFFIX
|
@@ -39,7 +39,6 @@ from classiq.interface.generator.functions.classical_function_declaration import
|
|
39
39
|
from classiq.interface.generator.functions.classical_type import (
|
40
40
|
Bool,
|
41
41
|
ClassicalArray,
|
42
|
-
ClassicalList,
|
43
42
|
ClassicalTuple,
|
44
43
|
ClassicalType,
|
45
44
|
OpaqueHandle,
|
@@ -91,7 +90,7 @@ def qmod_val_to_python(val: ExpressionValue, qmod_type: ClassicalType) -> Any:
|
|
91
90
|
if isinstance(val, (Enum, int)):
|
92
91
|
return val
|
93
92
|
|
94
|
-
elif isinstance(qmod_type,
|
93
|
+
elif isinstance(qmod_type, ClassicalArray):
|
95
94
|
if isinstance(val, list):
|
96
95
|
return [qmod_val_to_python(elem, qmod_type.element_type) for elem in val]
|
97
96
|
|
@@ -145,9 +144,9 @@ def python_val_to_qmod(val: Any, qmod_type: ClassicalType) -> ExpressionValue:
|
|
145
144
|
field_name: python_val_to_qmod(val[field_name], field_type)
|
146
145
|
for field_name, field_type in struct_decl.variables.items()
|
147
146
|
}
|
148
|
-
return QmodStructInstance(struct_decl.model_copy(), qmod_dict)
|
147
|
+
return QmodStructInstance(struct_decl.model_copy(deep=True), qmod_dict)
|
149
148
|
|
150
|
-
if isinstance(qmod_type,
|
149
|
+
if isinstance(qmod_type, ClassicalArray):
|
151
150
|
if not isinstance(val, list):
|
152
151
|
raise ClassiqInternalExpansionError("Bad value for list")
|
153
152
|
return [python_val_to_qmod(elem, qmod_type.element_type) for elem in val]
|
@@ -182,7 +181,7 @@ def python_call_wrapper(func: Callable, *args: ExpressionValue) -> Any:
|
|
182
181
|
|
183
182
|
def struct_literal(struct_type_symbol: Symbol, **kwargs: Any) -> QmodStructInstance:
|
184
183
|
return QmodStructInstance(
|
185
|
-
QMODULE.type_decls[struct_type_symbol.name].model_copy(),
|
184
|
+
QMODULE.type_decls[struct_type_symbol.name].model_copy(deep=True),
|
186
185
|
{field: sympy_to_python(field_value) for field, field_value in kwargs.items()},
|
187
186
|
)
|
188
187
|
|
@@ -330,6 +329,40 @@ def mod_inverse(a: Any, b: Any) -> Any:
|
|
330
329
|
return sympy.mod_inverse(a, b)
|
331
330
|
|
332
331
|
|
332
|
+
def min_wrapper(*vals: Any) -> Any:
|
333
|
+
try:
|
334
|
+
return sympy.Min(*vals)
|
335
|
+
except ValueError:
|
336
|
+
return AnyClassicalValue(f"Min({', '.join(map(str, vals))})")
|
337
|
+
|
338
|
+
|
339
|
+
min_wrapper.__name__ = "min"
|
340
|
+
|
341
|
+
|
342
|
+
def Min_wrapper(*vals: Any) -> Any: # noqa: N802
|
343
|
+
return min_wrapper(*vals)
|
344
|
+
|
345
|
+
|
346
|
+
Min_wrapper.__name__ = "Min"
|
347
|
+
|
348
|
+
|
349
|
+
def max_wrapper(*vals: Any) -> Any:
|
350
|
+
try:
|
351
|
+
return sympy.Max(*vals)
|
352
|
+
except ValueError:
|
353
|
+
return AnyClassicalValue(f"Max({', '.join(map(str, vals))})")
|
354
|
+
|
355
|
+
|
356
|
+
max_wrapper.__name__ = "max"
|
357
|
+
|
358
|
+
|
359
|
+
def Max_wrapper(*vals: Any) -> Any: # noqa: N802
|
360
|
+
return max_wrapper(*vals)
|
361
|
+
|
362
|
+
|
363
|
+
Max_wrapper.__name__ = "Max"
|
364
|
+
|
365
|
+
|
333
366
|
CORE_LIB_FUNCTIONS_LIST: list[Callable] = [
|
334
367
|
print,
|
335
368
|
do_sum,
|
@@ -347,6 +380,10 @@ CORE_LIB_FUNCTIONS_LIST: list[Callable] = [
|
|
347
380
|
RShift,
|
348
381
|
LShift,
|
349
382
|
mod_inverse,
|
383
|
+
min_wrapper,
|
384
|
+
Min_wrapper,
|
385
|
+
max_wrapper,
|
386
|
+
Max_wrapper,
|
350
387
|
]
|
351
388
|
|
352
389
|
|
@@ -39,14 +39,14 @@ from classiq.interface.model.quantum_lambda_function import (
|
|
39
39
|
)
|
40
40
|
from classiq.interface.model.quantum_statement import QuantumStatement
|
41
41
|
|
42
|
+
from classiq.evaluators.classical_expression import (
|
43
|
+
evaluate_classical_expression,
|
44
|
+
)
|
42
45
|
from classiq.model_expansions.closure import (
|
43
46
|
Closure,
|
44
47
|
FunctionClosure,
|
45
48
|
)
|
46
49
|
from classiq.model_expansions.debug_flag import debug_mode
|
47
|
-
from classiq.model_expansions.evaluators.classical_expression import (
|
48
|
-
evaluate_classical_expression,
|
49
|
-
)
|
50
50
|
from classiq.model_expansions.function_builder import (
|
51
51
|
FunctionContext,
|
52
52
|
OperationBuilder,
|
@@ -12,7 +12,7 @@ from classiq.interface.model.quantum_type import (
|
|
12
12
|
QuantumNumeric,
|
13
13
|
)
|
14
14
|
|
15
|
-
from classiq.
|
15
|
+
from classiq.evaluators.quantum_type_utils import copy_type_information
|
16
16
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
17
17
|
from classiq.model_expansions.scope import QuantumSymbol
|
18
18
|
|
@@ -24,7 +24,7 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
24
24
|
)
|
25
25
|
from classiq.interface.model.within_apply_operation import WithinApply
|
26
26
|
|
27
|
-
from classiq.
|
27
|
+
from classiq.evaluators.quantum_type_utils import copy_type_information
|
28
28
|
from classiq.model_expansions.quantum_operations.arithmetic.explicit_boolean_expressions import (
|
29
29
|
convert_assignment_bool_expression,
|
30
30
|
validate_assignment_bool_expression,
|
@@ -8,10 +8,10 @@ from classiq.interface.exceptions import (
|
|
8
8
|
from classiq.interface.model.bind_operation import BindOperation
|
9
9
|
from classiq.interface.model.quantum_type import QuantumNumeric
|
10
10
|
|
11
|
-
from classiq.
|
11
|
+
from classiq.evaluators.parameter_types import (
|
12
12
|
evaluate_types_in_quantum_symbols,
|
13
13
|
)
|
14
|
-
from classiq.
|
14
|
+
from classiq.evaluators.quantum_type_utils import (
|
15
15
|
set_size,
|
16
16
|
validate_bind_targets,
|
17
17
|
)
|