classiq 0.39.0__py3-none-any.whl → 0.41.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/__init__.py +5 -2
- classiq/_internals/api_wrapper.py +3 -21
- classiq/applications/chemistry/chemistry_model_constructor.py +87 -101
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +7 -26
- classiq/applications/combinatorial_helpers/optimization_model.py +7 -6
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +33 -55
- classiq/applications/combinatorial_optimization/__init__.py +4 -0
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +29 -26
- classiq/applications/finance/finance_model_constructor.py +23 -26
- classiq/applications/grover/grover_model_constructor.py +37 -38
- classiq/applications/qsvm/qsvm.py +1 -2
- classiq/applications/qsvm/qsvm_model_constructor.py +15 -16
- classiq/execution/__init__.py +4 -0
- classiq/execution/execution_session.py +151 -0
- classiq/execution/qnn.py +80 -0
- classiq/executor.py +2 -109
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +11 -0
- classiq/interface/applications/qsvm.py +0 -8
- classiq/interface/ast_node.py +12 -2
- classiq/interface/backend/backend_preferences.py +30 -6
- classiq/interface/backend/quantum_backend_providers.py +11 -11
- classiq/interface/executor/execution_preferences.py +7 -67
- classiq/interface/executor/execution_result.py +22 -1
- classiq/interface/generator/application_apis/chemistry_declarations.py +2 -4
- classiq/interface/generator/application_apis/finance_declarations.py +1 -1
- classiq/interface/generator/arith/binary_ops.py +88 -25
- classiq/interface/generator/arith/unary_ops.py +28 -19
- classiq/interface/generator/expressions/atomic_expression_functions.py +6 -2
- classiq/interface/generator/expressions/enums/__init__.py +10 -0
- classiq/interface/generator/expressions/enums/classical_enum.py +5 -1
- classiq/interface/generator/expressions/expression.py +9 -2
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +89 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +20 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +22 -0
- classiq/interface/generator/expressions/sympy_supported_expressions.py +10 -1
- classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +8 -6
- classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +10 -4
- classiq/interface/generator/functions/builtins/internal_operators.py +7 -62
- classiq/interface/generator/functions/builtins/open_lib_functions.py +1627 -271
- classiq/interface/generator/functions/classical_type.py +27 -17
- classiq/interface/generator/model/preferences/preferences.py +4 -2
- classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
- classiq/interface/model/bind_operation.py +3 -1
- classiq/interface/model/call_synthesis_data.py +2 -13
- classiq/interface/model/classical_if.py +3 -1
- classiq/interface/model/classical_parameter_declaration.py +13 -0
- classiq/interface/model/control.py +6 -8
- classiq/interface/model/inplace_binary_operation.py +3 -1
- classiq/interface/model/invert.py +3 -1
- classiq/interface/model/port_declaration.py +8 -1
- classiq/interface/model/power.py +3 -1
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +4 -2
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +3 -1
- classiq/interface/model/quantum_expressions/quantum_expression.py +11 -1
- classiq/interface/model/quantum_function_call.py +4 -10
- classiq/interface/model/quantum_function_declaration.py +26 -4
- classiq/interface/model/quantum_lambda_function.py +1 -20
- classiq/interface/model/quantum_statement.py +9 -2
- classiq/interface/model/quantum_type.py +6 -5
- classiq/interface/model/repeat.py +3 -1
- classiq/interface/model/resolvers/function_call_resolver.py +0 -5
- classiq/interface/model/statement_block.py +19 -16
- classiq/interface/model/validations/handles_validator.py +8 -2
- classiq/interface/model/variable_declaration_statement.py +3 -1
- classiq/interface/model/within_apply_operation.py +3 -1
- classiq/interface/server/routes.py +0 -5
- classiq/qmod/__init__.py +5 -2
- classiq/qmod/builtins/classical_execution_primitives.py +22 -2
- classiq/qmod/builtins/classical_functions.py +30 -35
- classiq/qmod/builtins/functions.py +263 -153
- classiq/qmod/builtins/operations.py +50 -26
- classiq/qmod/builtins/structs.py +50 -48
- classiq/qmod/declaration_inferrer.py +32 -27
- classiq/qmod/native/__init__.py +9 -0
- classiq/qmod/native/expression_to_qmod.py +8 -4
- classiq/qmod/native/pretty_printer.py +11 -18
- classiq/qmod/pretty_print/__init__.py +9 -0
- classiq/qmod/pretty_print/expression_to_python.py +221 -0
- classiq/qmod/pretty_print/pretty_printer.py +421 -0
- classiq/qmod/qmod_constant.py +7 -7
- classiq/qmod/qmod_parameter.py +57 -33
- classiq/qmod/qmod_struct.py +2 -2
- classiq/qmod/qmod_variable.py +40 -29
- classiq/qmod/quantum_callable.py +8 -4
- classiq/qmod/quantum_expandable.py +22 -15
- classiq/qmod/quantum_function.py +15 -4
- classiq/qmod/symbolic.py +73 -68
- classiq/qmod/symbolic_expr.py +1 -1
- classiq/qmod/symbolic_type.py +1 -4
- classiq/qmod/utilities.py +29 -0
- classiq/synthesis.py +15 -16
- {classiq-0.39.0.dist-info → classiq-0.41.0.dist-info}/METADATA +5 -4
- {classiq-0.39.0.dist-info → classiq-0.41.0.dist-info}/RECORD +95 -94
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
- classiq/interface/model/common_model_types.py +0 -23
- classiq/interface/model/quantum_expressions/control_state.py +0 -38
- classiq/interface/model/quantum_if_operation.py +0 -94
- {classiq-0.39.0.dist-info → classiq-0.41.0.dist-info}/WHEEL +0 -0
@@ -14,6 +14,8 @@ from classiq.interface.generator.expressions.enums.pauli import Pauli as PauliEn
|
|
14
14
|
from classiq.interface.generator.expressions.expression_types import RuntimeExpression
|
15
15
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
16
16
|
|
17
|
+
CLASSICAL_ATTRIBUTES = {"len", "size", "is_signed", "fraction_digits"}
|
18
|
+
|
17
19
|
NamedSymbol = Union[IndexedBase, Symbol]
|
18
20
|
|
19
21
|
|
@@ -29,9 +31,9 @@ class ClassicalType(HashableASTNode):
|
|
29
31
|
)
|
30
32
|
|
31
33
|
@property
|
32
|
-
def
|
34
|
+
def qmod_type(self) -> type:
|
33
35
|
raise NotImplementedError(
|
34
|
-
f"{self.__class__.__name__!r} has no
|
36
|
+
f"{self.__class__.__name__!r} has no QMOD SDK equivalent"
|
35
37
|
)
|
36
38
|
|
37
39
|
class Config:
|
@@ -53,8 +55,10 @@ class Integer(ClassicalType):
|
|
53
55
|
return values_with_discriminator(values, "kind", "int")
|
54
56
|
|
55
57
|
@property
|
56
|
-
def
|
57
|
-
|
58
|
+
def qmod_type(self) -> type:
|
59
|
+
from classiq.qmod.qmod_parameter import CInt
|
60
|
+
|
61
|
+
return CInt
|
58
62
|
|
59
63
|
|
60
64
|
class Real(ClassicalType):
|
@@ -72,8 +76,10 @@ class Real(ClassicalType):
|
|
72
76
|
return values_with_discriminator(values, "kind", "real")
|
73
77
|
|
74
78
|
@property
|
75
|
-
def
|
76
|
-
|
79
|
+
def qmod_type(self) -> type:
|
80
|
+
from classiq.qmod.qmod_parameter import CReal
|
81
|
+
|
82
|
+
return CReal
|
77
83
|
|
78
84
|
|
79
85
|
class Bool(ClassicalType):
|
@@ -88,8 +94,10 @@ class Bool(ClassicalType):
|
|
88
94
|
return values_with_discriminator(values, "kind", "bool")
|
89
95
|
|
90
96
|
@property
|
91
|
-
def
|
92
|
-
|
97
|
+
def qmod_type(self) -> type:
|
98
|
+
from classiq.qmod.qmod_parameter import CBool
|
99
|
+
|
100
|
+
return CBool
|
93
101
|
|
94
102
|
|
95
103
|
class ClassicalList(ClassicalType):
|
@@ -108,8 +116,10 @@ class ClassicalList(ClassicalType):
|
|
108
116
|
return values_with_discriminator(values, "kind", "list")
|
109
117
|
|
110
118
|
@property
|
111
|
-
def
|
112
|
-
|
119
|
+
def qmod_type(self) -> type:
|
120
|
+
from classiq.qmod.qmod_parameter import CArray
|
121
|
+
|
122
|
+
return CArray[self.element_type.qmod_type] # type:ignore[name-defined]
|
113
123
|
|
114
124
|
|
115
125
|
class Pauli(ClassicalType):
|
@@ -124,8 +134,8 @@ class Pauli(ClassicalType):
|
|
124
134
|
return values_with_discriminator(values, "kind", "pauli")
|
125
135
|
|
126
136
|
@property
|
127
|
-
def
|
128
|
-
return
|
137
|
+
def qmod_type(self) -> type:
|
138
|
+
return PauliEnum
|
129
139
|
|
130
140
|
|
131
141
|
class StructMetaType(ClassicalType):
|
@@ -140,7 +150,7 @@ class StructMetaType(ClassicalType):
|
|
140
150
|
return values_with_discriminator(values, "kind", "type_proxy")
|
141
151
|
|
142
152
|
|
143
|
-
class
|
153
|
+
class CStructBase: # marker for Qmod structs in the Python SDK
|
144
154
|
pass
|
145
155
|
|
146
156
|
|
@@ -157,8 +167,8 @@ class Struct(ClassicalType):
|
|
157
167
|
return values_with_discriminator(values, "kind", "struct_instance")
|
158
168
|
|
159
169
|
@property
|
160
|
-
def
|
161
|
-
return type(self.name, (
|
170
|
+
def qmod_type(self) -> type:
|
171
|
+
return type(self.name, (CStructBase,), dict())
|
162
172
|
|
163
173
|
|
164
174
|
class ClassicalArray(ClassicalType):
|
@@ -228,8 +238,8 @@ class LadderOperator(ClassicalType):
|
|
228
238
|
return values_with_discriminator(values, "kind", "ladder_operator")
|
229
239
|
|
230
240
|
@property
|
231
|
-
def
|
232
|
-
return
|
241
|
+
def qmod_type(self) -> type:
|
242
|
+
return LadderOperatorEnum
|
233
243
|
|
234
244
|
|
235
245
|
ConcreteClassicalType = Annotated[
|
@@ -11,7 +11,9 @@ from classiq.interface.backend.quantum_backend_providers import (
|
|
11
11
|
AllBackendsNameByVendor,
|
12
12
|
ProviderVendor,
|
13
13
|
)
|
14
|
-
from classiq.interface.generator.arith.
|
14
|
+
from classiq.interface.generator.arith.machine_precision import (
|
15
|
+
DEFAULT_MACHINE_PRECISION,
|
16
|
+
)
|
15
17
|
from classiq.interface.generator.hardware.hardware_data import (
|
16
18
|
BACKEND_VALIDATION_ERROR_MESSAGE,
|
17
19
|
CustomHardwareSettings,
|
@@ -78,7 +80,7 @@ class Preferences(pydantic.BaseModel, extra=pydantic.Extra.forbid):
|
|
78
80
|
_backend_preferences: Optional[BackendPreferences] = pydantic.PrivateAttr(
|
79
81
|
default=None
|
80
82
|
)
|
81
|
-
machine_precision: PydanticMachinePrecision =
|
83
|
+
machine_precision: PydanticMachinePrecision = DEFAULT_MACHINE_PRECISION
|
82
84
|
|
83
85
|
backend_service_provider: Optional[Union[Provider, ProviderVendor, str]] = (
|
84
86
|
pydantic.Field(
|
@@ -1,10 +1,7 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
import pydantic
|
4
2
|
|
5
3
|
|
6
4
|
class SynthesisStepDurations(pydantic.BaseModel):
|
7
|
-
model_preprocessing: Optional[float] = None
|
8
5
|
preprocessing: float
|
9
6
|
solving: float
|
10
7
|
conversion_to_circuit: float
|
@@ -14,7 +11,6 @@ class SynthesisStepDurations(pydantic.BaseModel):
|
|
14
11
|
return sum(
|
15
12
|
time if time is not None else 0
|
16
13
|
for time in (
|
17
|
-
self.model_preprocessing,
|
18
14
|
self.preprocessing,
|
19
15
|
self.solving,
|
20
16
|
self.conversion_to_circuit,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import List, Mapping
|
1
|
+
from typing import List, Literal, Mapping
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
@@ -12,6 +12,8 @@ BIND_OUTPUT_NAME = "bind_output"
|
|
12
12
|
|
13
13
|
|
14
14
|
class BindOperation(QuantumOperation):
|
15
|
+
kind: Literal["BindOperation"]
|
16
|
+
|
15
17
|
in_handles: List[HandleBinding]
|
16
18
|
out_handles: List[HandleBinding]
|
17
19
|
|
@@ -36,24 +36,13 @@ class CallSynthesisData(Mapping):
|
|
36
36
|
should_control=self.should_control and other.should_control,
|
37
37
|
)
|
38
38
|
|
39
|
-
def set_control(self, ctrl_name: str, ctrl_size: int) -> None:
|
39
|
+
def set_control(self, ctrl_name: str, ctrl_size: int, ctrl_state: str) -> None:
|
40
40
|
self.control_states = [
|
41
41
|
ControlState(
|
42
|
-
name=ctrl_name,
|
43
|
-
num_ctrl_qubits=ctrl_size,
|
42
|
+
name=ctrl_name, num_ctrl_qubits=ctrl_size, ctrl_state=ctrl_state
|
44
43
|
)
|
45
44
|
]
|
46
45
|
|
47
|
-
def update_control_state(self, ctrl_size: int, ctrl_state: str) -> None:
|
48
|
-
prev_ctrl_state = self.control_states.pop()
|
49
|
-
self.control_states.append(
|
50
|
-
ControlState(
|
51
|
-
name=prev_ctrl_state.name,
|
52
|
-
num_ctrl_qubits=ctrl_size,
|
53
|
-
ctrl_state=ctrl_state,
|
54
|
-
)
|
55
|
-
)
|
56
|
-
|
57
46
|
@property
|
58
47
|
def has_control(self) -> bool:
|
59
48
|
return bool(self.control_states)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import TYPE_CHECKING
|
1
|
+
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
3
|
from classiq.interface.generator.expressions.expression import Expression
|
4
4
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
@@ -8,6 +8,8 @@ if TYPE_CHECKING:
|
|
8
8
|
|
9
9
|
|
10
10
|
class ClassicalIf(QuantumOperation):
|
11
|
+
kind: Literal["ClassicalIf"]
|
12
|
+
|
11
13
|
condition: Expression
|
12
14
|
then: "StatementBlock"
|
13
15
|
else_: "StatementBlock"
|
@@ -1,7 +1,20 @@
|
|
1
|
+
from typing import Any, Dict, Literal
|
2
|
+
|
3
|
+
import pydantic
|
4
|
+
|
1
5
|
from classiq.interface.ast_node import ASTNode
|
2
6
|
from classiq.interface.generator.functions.classical_type import ConcreteClassicalType
|
7
|
+
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
3
8
|
|
4
9
|
|
5
10
|
class ClassicalParameterDeclaration(ASTNode):
|
11
|
+
kind: Literal["ClassicalParameterDeclaration"]
|
12
|
+
|
6
13
|
name: str
|
7
14
|
classical_type: ConcreteClassicalType
|
15
|
+
|
16
|
+
@pydantic.root_validator(pre=True)
|
17
|
+
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
18
|
+
return values_with_discriminator(
|
19
|
+
values, "kind", "ClassicalParameterDeclaration"
|
20
|
+
)
|
@@ -1,16 +1,14 @@
|
|
1
|
-
from typing import TYPE_CHECKING,
|
1
|
+
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
|
-
from classiq.interface.model.
|
4
|
-
|
5
|
-
SlicedHandleBinding,
|
6
|
-
SubscriptHandleBinding,
|
3
|
+
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
4
|
+
QuantumExpressionOperation,
|
7
5
|
)
|
8
|
-
from classiq.interface.model.quantum_statement import QuantumOperation
|
9
6
|
|
10
7
|
if TYPE_CHECKING:
|
11
8
|
from classiq.interface.model.statement_block import StatementBlock
|
12
9
|
|
13
10
|
|
14
|
-
class Control(
|
15
|
-
|
11
|
+
class Control(QuantumExpressionOperation):
|
12
|
+
kind: Literal["Control"]
|
13
|
+
|
16
14
|
body: "StatementBlock"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Mapping
|
1
|
+
from typing import Literal, Mapping
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
@@ -23,6 +23,8 @@ class BinaryOperation(StrEnum):
|
|
23
23
|
|
24
24
|
|
25
25
|
class InplaceBinaryOperation(QuantumOperation):
|
26
|
+
kind: Literal["InplaceBinaryOperation"]
|
27
|
+
|
26
28
|
target: HandleBinding
|
27
29
|
value: HandleBinding
|
28
30
|
operation: BinaryOperation
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import TYPE_CHECKING
|
1
|
+
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
3
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
4
4
|
|
@@ -7,4 +7,6 @@ if TYPE_CHECKING:
|
|
7
7
|
|
8
8
|
|
9
9
|
class Invert(QuantumOperation):
|
10
|
+
kind: Literal["Invert"]
|
11
|
+
|
10
12
|
body: "StatementBlock"
|
@@ -1,10 +1,11 @@
|
|
1
|
-
from typing import Any, Mapping
|
1
|
+
from typing import Any, Dict, Literal, Mapping
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
5
5
|
from classiq.interface.generator.functions.port_declaration import (
|
6
6
|
PortDeclarationDirection,
|
7
7
|
)
|
8
|
+
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
8
9
|
from classiq.interface.model.quantum_variable_declaration import (
|
9
10
|
QuantumVariableDeclaration,
|
10
11
|
)
|
@@ -13,8 +14,14 @@ from classiq.exceptions import ClassiqValueError
|
|
13
14
|
|
14
15
|
|
15
16
|
class PortDeclaration(QuantumVariableDeclaration):
|
17
|
+
kind: Literal["PortDeclaration"]
|
18
|
+
|
16
19
|
direction: PortDeclarationDirection
|
17
20
|
|
21
|
+
@pydantic.root_validator(pre=True)
|
22
|
+
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
23
|
+
return values_with_discriminator(values, "kind", "PortDeclaration")
|
24
|
+
|
18
25
|
@pydantic.validator("direction")
|
19
26
|
def _direction_validator(
|
20
27
|
cls, direction: PortDeclarationDirection, values: Mapping[str, Any]
|
classiq/interface/model/power.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import TYPE_CHECKING
|
1
|
+
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
3
|
from classiq.interface.generator.expressions.expression import Expression
|
4
4
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
@@ -8,5 +8,7 @@ if TYPE_CHECKING:
|
|
8
8
|
|
9
9
|
|
10
10
|
class Power(QuantumOperation):
|
11
|
+
kind: Literal["Power"]
|
12
|
+
|
11
13
|
power: Expression
|
12
14
|
body: "StatementBlock"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Dict, Mapping, Union
|
1
|
+
from typing import Dict, Literal, Mapping, Union
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
@@ -28,6 +28,8 @@ VAR_DOMAIN_ILLEGAL = (
|
|
28
28
|
|
29
29
|
|
30
30
|
class AmplitudeLoadingOperation(QuantumAssignmentOperation):
|
31
|
+
kind: Literal["AmplitudeLoadingOperation"]
|
32
|
+
|
31
33
|
_result_type: QuantumType = pydantic.PrivateAttr(default_factory=QuantumBit)
|
32
34
|
|
33
35
|
@property
|
@@ -52,7 +54,7 @@ class AmplitudeLoadingOperation(QuantumAssignmentOperation):
|
|
52
54
|
) -> None:
|
53
55
|
if len(var_types) != 1:
|
54
56
|
raise ClassiqValueError(MULTI_VARS_UNSUPPORTED_ERROR)
|
55
|
-
var_type = var_types
|
57
|
+
var_type = list(var_types.values())[0]
|
56
58
|
if not (
|
57
59
|
isinstance(var_type, QuantumNumeric)
|
58
60
|
and var_type.fraction_digits_value == var_type.size_in_bits
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Dict, Mapping, Union
|
1
|
+
from typing import Dict, Literal, Mapping, Union
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
@@ -18,6 +18,8 @@ from classiq.interface.model.quantum_type import QuantumType
|
|
18
18
|
|
19
19
|
|
20
20
|
class ArithmeticOperation(QuantumAssignmentOperation):
|
21
|
+
kind: Literal["ArithmeticOperation"]
|
22
|
+
|
21
23
|
inplace_result: bool = pydantic.Field(
|
22
24
|
description="Determines whether the result variable is initialized",
|
23
25
|
)
|
@@ -33,6 +33,16 @@ class VarRefCollector(ast.NodeVisitor):
|
|
33
33
|
super().generic_visit(node)
|
34
34
|
|
35
35
|
|
36
|
+
class VarRefTransformer(ast.NodeTransformer):
|
37
|
+
def __init__(self, var_mapping: Dict[str, str]) -> None:
|
38
|
+
self.var_mapping = var_mapping
|
39
|
+
|
40
|
+
def visit_Name(self, node: ast.Name) -> ast.Name:
|
41
|
+
if node.id in self.var_mapping:
|
42
|
+
node.id = self.var_mapping[node.id]
|
43
|
+
return node
|
44
|
+
|
45
|
+
|
36
46
|
class QuantumExpressionOperation(QuantumOperation):
|
37
47
|
expression: Expression = pydantic.Field()
|
38
48
|
_var_handles: List[HandleBinding] = pydantic.PrivateAttr(
|
@@ -58,7 +68,7 @@ class QuantumExpressionOperation(QuantumOperation):
|
|
58
68
|
var_types: Dict[str, QuantumType],
|
59
69
|
machine_precision: int,
|
60
70
|
) -> None:
|
61
|
-
assert len(var_types) == len(self.var_handles)
|
71
|
+
assert len(var_types) == len(self.var_handles) or len(self.var_handles) == 0
|
62
72
|
self._var_types = var_types
|
63
73
|
|
64
74
|
@property
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import itertools
|
2
2
|
import re
|
3
|
-
from typing import Any, Dict, List, Mapping, Optional, Set, Type, Union
|
3
|
+
from typing import Any, Dict, List, Literal, Mapping, Optional, Set, Type, Union
|
4
4
|
|
5
5
|
import pydantic
|
6
6
|
|
@@ -23,7 +23,6 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
23
23
|
QuantumOperandDeclaration,
|
24
24
|
)
|
25
25
|
from classiq.interface.model.quantum_lambda_function import (
|
26
|
-
LambdaListComprehension,
|
27
26
|
QuantumCallable,
|
28
27
|
QuantumLambdaFunction,
|
29
28
|
QuantumOperand,
|
@@ -114,6 +113,8 @@ class OperandIdentifier(ASTNode):
|
|
114
113
|
|
115
114
|
|
116
115
|
class QuantumFunctionCall(QuantumOperation):
|
116
|
+
kind: Literal["QuantumFunctionCall"]
|
117
|
+
|
117
118
|
function: Union[str, OperandIdentifier] = pydantic.Field(
|
118
119
|
description="The function that is called"
|
119
120
|
)
|
@@ -304,10 +305,7 @@ class QuantumFunctionCall(QuantumOperation):
|
|
304
305
|
def get_lambda_defs(operand: QuantumOperand) -> List[QuantumCallable]:
|
305
306
|
if isinstance(operand, list):
|
306
307
|
return operand
|
307
|
-
|
308
|
-
return [operand.func]
|
309
|
-
else:
|
310
|
-
return [operand]
|
308
|
+
return [operand]
|
311
309
|
|
312
310
|
|
313
311
|
def _check_ports_against_declaration(
|
@@ -368,10 +366,6 @@ def _check_operand_against_declaration(
|
|
368
366
|
if operand_argument.func_decl is None:
|
369
367
|
return
|
370
368
|
operand_arg_decl = operand_argument.func_decl
|
371
|
-
elif isinstance(operand_argument, LambdaListComprehension):
|
372
|
-
if operand_argument.func.func_decl is None:
|
373
|
-
return
|
374
|
-
operand_arg_decl = operand_argument.func.func_decl
|
375
369
|
else:
|
376
370
|
raise ClassiqValueError(
|
377
371
|
f"{str(operand_argument)!r} argument to {call.func_decl.name!r} is not a "
|
@@ -1,6 +1,18 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import (
|
2
|
+
Any,
|
3
|
+
ClassVar,
|
4
|
+
Dict,
|
5
|
+
List,
|
6
|
+
Literal,
|
7
|
+
Mapping,
|
8
|
+
Sequence,
|
9
|
+
Set,
|
10
|
+
Type,
|
11
|
+
Union,
|
12
|
+
)
|
2
13
|
|
3
14
|
import pydantic
|
15
|
+
from typing_extensions import Annotated
|
4
16
|
|
5
17
|
from classiq.interface.generator.function_params import ArithmeticIODict, PortDirection
|
6
18
|
from classiq.interface.generator.functions.function_declaration import (
|
@@ -9,7 +21,10 @@ from classiq.interface.generator.functions.function_declaration import (
|
|
9
21
|
from classiq.interface.generator.functions.port_declaration import (
|
10
22
|
PortDeclarationDirection,
|
11
23
|
)
|
12
|
-
from classiq.interface.helpers.pydantic_model_helpers import
|
24
|
+
from classiq.interface.helpers.pydantic_model_helpers import (
|
25
|
+
Nameable,
|
26
|
+
values_with_discriminator,
|
27
|
+
)
|
13
28
|
from classiq.interface.helpers.validation_helpers import (
|
14
29
|
validate_nameables_mapping,
|
15
30
|
validate_nameables_no_overlap,
|
@@ -49,8 +64,9 @@ def _populate_declaration_dicts_with_positional_lists(
|
|
49
64
|
)
|
50
65
|
|
51
66
|
|
52
|
-
PositionalArg =
|
53
|
-
ClassicalParameterDeclaration, "QuantumOperandDeclaration", PortDeclaration
|
67
|
+
PositionalArg = Annotated[
|
68
|
+
Union[ClassicalParameterDeclaration, "QuantumOperandDeclaration", PortDeclaration],
|
69
|
+
pydantic.Field(..., discriminator="kind"),
|
54
70
|
]
|
55
71
|
|
56
72
|
|
@@ -218,10 +234,16 @@ class QuantumFunctionDeclaration(FunctionDeclaration):
|
|
218
234
|
|
219
235
|
|
220
236
|
class QuantumOperandDeclaration(QuantumFunctionDeclaration):
|
237
|
+
kind: Literal["QuantumOperandDeclaration"]
|
238
|
+
|
221
239
|
is_list: bool = pydantic.Field(
|
222
240
|
description="Indicate whether the operand expects an unnamed list of lambdas",
|
223
241
|
default=False,
|
224
242
|
)
|
225
243
|
|
244
|
+
@pydantic.root_validator(pre=True)
|
245
|
+
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
246
|
+
return values_with_discriminator(values, "kind", "QuantumOperandDeclaration")
|
247
|
+
|
226
248
|
|
227
249
|
QuantumFunctionDeclaration.update_forward_refs()
|
@@ -3,7 +3,6 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Union
|
|
3
3
|
import pydantic
|
4
4
|
|
5
5
|
from classiq.interface.ast_node import ASTNode
|
6
|
-
from classiq.interface.generator.expressions.expression import Expression
|
7
6
|
from classiq.interface.model.quantum_function_declaration import (
|
8
7
|
QuantumOperandDeclaration,
|
9
8
|
)
|
@@ -36,23 +35,5 @@ class QuantumLambdaFunction(ASTNode):
|
|
36
35
|
self._func_decl = fd
|
37
36
|
|
38
37
|
|
39
|
-
class LambdaListComprehension(ASTNode):
|
40
|
-
"""
|
41
|
-
Specification of a list of lambda functions iteratively
|
42
|
-
"""
|
43
|
-
|
44
|
-
count: Expression = pydantic.Field(
|
45
|
-
description="The number of lambda functions in the list"
|
46
|
-
)
|
47
|
-
|
48
|
-
index_var: str = pydantic.Field(
|
49
|
-
description="The name of the integer variable holding the iteration index"
|
50
|
-
)
|
51
|
-
|
52
|
-
func: QuantumLambdaFunction = pydantic.Field(
|
53
|
-
description="A lambda function definition replicated for index values 0 to count-1"
|
54
|
-
)
|
55
|
-
|
56
|
-
|
57
38
|
QuantumCallable = Union[str, QuantumLambdaFunction]
|
58
|
-
QuantumOperand = Union[QuantumCallable, List[QuantumCallable]
|
39
|
+
QuantumOperand = Union[QuantumCallable, List[QuantumCallable]]
|
@@ -1,8 +1,9 @@
|
|
1
|
-
from typing import Mapping, Union
|
1
|
+
from typing import Any, Dict, Mapping, Union
|
2
2
|
|
3
|
-
from pydantic import Extra
|
3
|
+
from pydantic import Extra, root_validator
|
4
4
|
|
5
5
|
from classiq.interface.ast_node import ASTNode
|
6
|
+
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
6
7
|
from classiq.interface.model.handle_binding import (
|
7
8
|
HandleBinding,
|
8
9
|
SlicedHandleBinding,
|
@@ -11,9 +12,15 @@ from classiq.interface.model.handle_binding import (
|
|
11
12
|
|
12
13
|
|
13
14
|
class QuantumStatement(ASTNode):
|
15
|
+
kind: str
|
16
|
+
|
14
17
|
class Config:
|
15
18
|
extra = Extra.forbid
|
16
19
|
|
20
|
+
@root_validator(pre=True)
|
21
|
+
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
22
|
+
return values_with_discriminator(values, "kind", cls.__name__) # type: ignore[attr-defined]
|
23
|
+
|
17
24
|
|
18
25
|
class QuantumOperation(QuantumStatement):
|
19
26
|
@property
|
@@ -10,6 +10,7 @@ from classiq.interface.generator.arith.register_user_input import (
|
|
10
10
|
RegisterUserInput,
|
11
11
|
)
|
12
12
|
from classiq.interface.generator.expressions.expression import Expression
|
13
|
+
from classiq.interface.generator.expressions.qmod_qarray_proxy import QmodQArrayProxy
|
13
14
|
from classiq.interface.generator.expressions.qmod_qscalar_proxy import (
|
14
15
|
QmodQNumProxy,
|
15
16
|
QmodQScalarProxy,
|
@@ -65,12 +66,9 @@ class QuantumBit(QuantumScalar):
|
|
65
66
|
return values_with_discriminator(values, "kind", "qbit")
|
66
67
|
|
67
68
|
|
68
|
-
class
|
69
|
-
length: Optional[Expression]
|
70
|
-
|
71
|
-
|
72
|
-
class QuantumBitvector(QuantumArray):
|
69
|
+
class QuantumBitvector(QuantumType):
|
73
70
|
kind: Literal["qvec"]
|
71
|
+
length: Optional[Expression]
|
74
72
|
|
75
73
|
@pydantic.root_validator(pre=True)
|
76
74
|
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
@@ -80,6 +78,9 @@ class QuantumBitvector(QuantumArray):
|
|
80
78
|
if self.length is not None and self.length.is_evaluated():
|
81
79
|
self._size_in_bits = self.length.to_int_value()
|
82
80
|
|
81
|
+
def get_proxy(self, name: str) -> QmodQArrayProxy:
|
82
|
+
return QmodQArrayProxy(name, self.size_in_bits)
|
83
|
+
|
83
84
|
|
84
85
|
class QuantumNumeric(QuantumScalar):
|
85
86
|
kind: Literal["qnum"]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import TYPE_CHECKING
|
1
|
+
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
3
|
from classiq.interface.generator.expressions.expression import Expression
|
4
4
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
@@ -8,6 +8,8 @@ if TYPE_CHECKING:
|
|
8
8
|
|
9
9
|
|
10
10
|
class Repeat(QuantumOperation):
|
11
|
+
kind: Literal["Repeat"]
|
12
|
+
|
11
13
|
iter_var: str
|
12
14
|
count: Expression
|
13
15
|
body: "StatementBlock"
|
@@ -9,7 +9,6 @@ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
9
9
|
from classiq.interface.model.quantum_function_declaration import (
|
10
10
|
QuantumFunctionDeclaration,
|
11
11
|
)
|
12
|
-
from classiq.interface.model.quantum_if_operation import QuantumIf
|
13
12
|
from classiq.interface.model.repeat import Repeat
|
14
13
|
from classiq.interface.model.within_apply_operation import WithinApply
|
15
14
|
|
@@ -33,10 +32,6 @@ class FunctionCallResolver(Visitor):
|
|
33
32
|
for fc in control.body:
|
34
33
|
self.visit(fc)
|
35
34
|
|
36
|
-
def visit_QuantumIf(self, quantum_if: QuantumIf) -> None:
|
37
|
-
for fc in quantum_if.then:
|
38
|
-
self.visit(fc)
|
39
|
-
|
40
35
|
def visit_WithinApply(self, within_apply: WithinApply) -> None:
|
41
36
|
for fc in itertools.chain(within_apply.compute, within_apply.action):
|
42
37
|
self.visit(fc)
|