classiq 0.38.0__py3-none-any.whl → 0.40.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 +22 -22
- classiq/_internals/api_wrapper.py +13 -1
- classiq/_internals/client.py +12 -2
- classiq/analyzer/analyzer.py +3 -1
- classiq/applications/__init__.py +1 -8
- classiq/applications/chemistry/__init__.py +6 -0
- classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +25 -6
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +2 -4
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +13 -16
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/pyomo_utils.py +4 -2
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +3 -10
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +4 -6
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +3 -5
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +4 -6
- classiq/applications/combinatorial_optimization/__init__.py +11 -3
- classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +9 -10
- classiq/applications/finance/__init__.py +3 -2
- classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +24 -14
- classiq/applications/grover/__init__.py +11 -0
- classiq/applications/libraries/qmci_library.py +35 -0
- classiq/applications/qsvm/__init__.py +5 -1
- classiq/execution/all_hardware_devices.py +13 -0
- classiq/executor.py +2 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/result.py +1 -5
- classiq/interface/applications/qsvm.py +4 -2
- classiq/interface/ast_node.py +23 -0
- classiq/interface/backend/backend_preferences.py +5 -5
- classiq/interface/backend/quantum_backend_providers.py +7 -7
- classiq/interface/combinatorial_optimization/examples/mht.py +8 -3
- classiq/interface/executor/execution_preferences.py +4 -9
- classiq/interface/executor/execution_request.py +2 -37
- classiq/interface/executor/vqe_result.py +1 -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/arithmetic_expression_validator.py +2 -0
- classiq/interface/generator/builtin_api_builder.py +0 -5
- classiq/interface/generator/constant.py +2 -3
- classiq/interface/generator/expressions/expression.py +2 -4
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +82 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +22 -1
- classiq/interface/generator/expressions/qmod_sized_proxy.py +22 -0
- classiq/interface/generator/functions/__init__.py +2 -2
- classiq/interface/generator/functions/builtins/__init__.py +15 -0
- classiq/interface/generator/functions/builtins/core_library/__init__.py +14 -0
- classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/atomic_quantum_functions.py +8 -6
- classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/exponentiation_functions.py +10 -4
- classiq/interface/generator/functions/builtins/internal_operators.py +62 -0
- classiq/interface/generator/functions/{core_lib_declarations/quantum_functions/std_lib_functions.py → builtins/open_lib_functions.py} +893 -319
- classiq/interface/generator/functions/builtins/quantum_operators.py +37 -0
- classiq/interface/generator/functions/classical_type.py +31 -21
- classiq/interface/generator/functions/function_declaration.py +2 -2
- classiq/interface/generator/hartree_fock.py +10 -2
- classiq/interface/generator/model/classical_main_validator.py +1 -1
- classiq/interface/generator/model/model.py +1 -1
- classiq/interface/generator/model/preferences/preferences.py +4 -2
- classiq/interface/generator/quantum_function_call.py +1 -1
- classiq/interface/generator/types/struct_declaration.py +2 -4
- classiq/interface/model/call_synthesis_data.py +3 -3
- classiq/interface/model/classical_if.py +13 -0
- classiq/interface/model/classical_parameter_declaration.py +2 -3
- classiq/interface/model/{quantum_if_operation.py → control.py} +39 -21
- classiq/interface/model/handle_binding.py +3 -2
- classiq/interface/model/invert.py +10 -0
- classiq/interface/model/model.py +2 -1
- classiq/interface/model/power.py +12 -0
- classiq/interface/model/quantum_function_call.py +9 -4
- classiq/interface/model/quantum_lambda_function.py +3 -9
- classiq/interface/model/quantum_statement.py +3 -2
- classiq/interface/model/quantum_type.py +8 -9
- classiq/interface/model/quantum_variable_declaration.py +2 -2
- classiq/interface/model/repeat.py +13 -0
- classiq/interface/model/resolvers/function_call_resolver.py +21 -0
- classiq/interface/model/statement_block.py +18 -4
- classiq/interface/model/validations/handles_validator.py +8 -12
- classiq/interface/model/within_apply_operation.py +4 -4
- classiq/interface/server/routes.py +0 -4
- classiq/qmod/__init__.py +6 -2
- classiq/qmod/builtins/classical_functions.py +34 -39
- classiq/qmod/builtins/functions.py +287 -300
- classiq/qmod/builtins/operations.py +217 -16
- classiq/qmod/builtins/structs.py +50 -48
- classiq/qmod/declaration_inferrer.py +30 -18
- classiq/qmod/native/expression_to_qmod.py +5 -4
- classiq/qmod/native/pretty_printer.py +48 -26
- classiq/qmod/qmod_constant.py +29 -5
- classiq/qmod/qmod_parameter.py +56 -34
- classiq/qmod/qmod_struct.py +2 -2
- classiq/qmod/qmod_variable.py +87 -43
- classiq/qmod/quantum_callable.py +8 -4
- classiq/qmod/quantum_expandable.py +25 -20
- classiq/qmod/quantum_function.py +29 -2
- classiq/qmod/symbolic.py +79 -69
- classiq/qmod/symbolic_expr.py +1 -1
- classiq/qmod/symbolic_type.py +1 -4
- classiq/qmod/utilities.py +29 -0
- {classiq-0.38.0.dist-info → classiq-0.40.0.dist-info}/METADATA +1 -1
- {classiq-0.38.0.dist-info → classiq-0.40.0.dist-info}/RECORD +122 -141
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -25
- classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
- classiq/builtin_functions/__init__.py +0 -43
- classiq/builtin_functions/amplitude_loading.py +0 -3
- classiq/builtin_functions/binary_ops.py +0 -1
- classiq/builtin_functions/exponentiation.py +0 -5
- classiq/builtin_functions/qpe.py +0 -4
- classiq/builtin_functions/qsvm.py +0 -7
- classiq/builtin_functions/range_types.py +0 -5
- classiq/builtin_functions/standard_gates.py +0 -1
- classiq/builtin_functions/state_preparation.py +0 -6
- classiq/builtin_functions/suzuki_trotter.py +0 -3
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py +0 -0
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
- classiq/model/__init__.py +0 -14
- classiq/model/composite_function_generator.py +0 -33
- classiq/model/function_handler.py +0 -462
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -229
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -205
- classiq/quantum_functions/decorators.py +0 -22
- classiq/quantum_functions/function_library.py +0 -181
- classiq/quantum_functions/function_parser.py +0 -74
- classiq/quantum_functions/quantum_function.py +0 -236
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
- /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +0 -0
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +0 -0
- /classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/libraries/ampltitude_estimation_library.py +0 -0
- /classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +0 -0
- /classiq/{quantum_register.py → interface/model/quantum_register.py} +0 -0
- {classiq-0.38.0.dist-info → classiq-0.40.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from classiq.interface.model.quantum_function_declaration import (
|
4
|
+
QuantumFunctionDeclaration,
|
5
|
+
QuantumOperandDeclaration,
|
6
|
+
)
|
7
|
+
|
8
|
+
|
9
|
+
def get_single_empty_operand_operator(
|
10
|
+
operator_name: str, **kwargs: Any
|
11
|
+
) -> QuantumFunctionDeclaration:
|
12
|
+
operand_field_name = "operand"
|
13
|
+
return QuantumFunctionDeclaration(
|
14
|
+
name=operator_name,
|
15
|
+
operand_declarations={
|
16
|
+
operand_field_name: QuantumOperandDeclaration(name=operand_field_name)
|
17
|
+
},
|
18
|
+
**kwargs,
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
PERMUTE_OPERATOR = QuantumFunctionDeclaration(
|
23
|
+
name="permute",
|
24
|
+
operand_declarations={
|
25
|
+
"functions": QuantumOperandDeclaration(
|
26
|
+
name="functions",
|
27
|
+
is_list=True,
|
28
|
+
)
|
29
|
+
},
|
30
|
+
)
|
31
|
+
|
32
|
+
APPLY_OPERATOR = get_single_empty_operand_operator(operator_name="apply")
|
33
|
+
|
34
|
+
STD_QMOD_OPERATORS = [
|
35
|
+
PERMUTE_OPERATOR,
|
36
|
+
APPLY_OPERATOR,
|
37
|
+
]
|
@@ -6,20 +6,22 @@ from pydantic import Extra, Field
|
|
6
6
|
from sympy import IndexedBase, Symbol
|
7
7
|
from typing_extensions import Annotated
|
8
8
|
|
9
|
+
from classiq.interface.ast_node import HashableASTNode
|
9
10
|
from classiq.interface.generator.expressions.enums.ladder_operator import (
|
10
11
|
LadderOperator as LadderOperatorEnum,
|
11
12
|
)
|
12
13
|
from classiq.interface.generator.expressions.enums.pauli import Pauli as PauliEnum
|
13
14
|
from classiq.interface.generator.expressions.expression_types import RuntimeExpression
|
14
|
-
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
15
|
-
HashablePydanticBaseModel,
|
16
|
-
)
|
17
15
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
18
16
|
|
17
|
+
CLASSICAL_ATTRIBUTES = {
|
18
|
+
"len": len,
|
19
|
+
}
|
20
|
+
|
19
21
|
NamedSymbol = Union[IndexedBase, Symbol]
|
20
22
|
|
21
23
|
|
22
|
-
class ClassicalType(
|
24
|
+
class ClassicalType(HashableASTNode):
|
23
25
|
def as_symbolic(self, name: str) -> Union[NamedSymbol, List[NamedSymbol]]:
|
24
26
|
return Symbol(name)
|
25
27
|
|
@@ -31,9 +33,9 @@ class ClassicalType(HashablePydanticBaseModel):
|
|
31
33
|
)
|
32
34
|
|
33
35
|
@property
|
34
|
-
def
|
36
|
+
def qmod_type(self) -> type:
|
35
37
|
raise NotImplementedError(
|
36
|
-
f"{self.__class__.__name__!r} has no
|
38
|
+
f"{self.__class__.__name__!r} has no QMOD SDK equivalent"
|
37
39
|
)
|
38
40
|
|
39
41
|
class Config:
|
@@ -55,8 +57,10 @@ class Integer(ClassicalType):
|
|
55
57
|
return values_with_discriminator(values, "kind", "int")
|
56
58
|
|
57
59
|
@property
|
58
|
-
def
|
59
|
-
|
60
|
+
def qmod_type(self) -> type:
|
61
|
+
from classiq.qmod.qmod_parameter import CInt
|
62
|
+
|
63
|
+
return CInt
|
60
64
|
|
61
65
|
|
62
66
|
class Real(ClassicalType):
|
@@ -74,8 +78,10 @@ class Real(ClassicalType):
|
|
74
78
|
return values_with_discriminator(values, "kind", "real")
|
75
79
|
|
76
80
|
@property
|
77
|
-
def
|
78
|
-
|
81
|
+
def qmod_type(self) -> type:
|
82
|
+
from classiq.qmod.qmod_parameter import CReal
|
83
|
+
|
84
|
+
return CReal
|
79
85
|
|
80
86
|
|
81
87
|
class Bool(ClassicalType):
|
@@ -90,8 +96,10 @@ class Bool(ClassicalType):
|
|
90
96
|
return values_with_discriminator(values, "kind", "bool")
|
91
97
|
|
92
98
|
@property
|
93
|
-
def
|
94
|
-
|
99
|
+
def qmod_type(self) -> type:
|
100
|
+
from classiq.qmod.qmod_parameter import CBool
|
101
|
+
|
102
|
+
return CBool
|
95
103
|
|
96
104
|
|
97
105
|
class ClassicalList(ClassicalType):
|
@@ -110,8 +118,10 @@ class ClassicalList(ClassicalType):
|
|
110
118
|
return values_with_discriminator(values, "kind", "list")
|
111
119
|
|
112
120
|
@property
|
113
|
-
def
|
114
|
-
|
121
|
+
def qmod_type(self) -> type:
|
122
|
+
from classiq.qmod.qmod_parameter import CArray
|
123
|
+
|
124
|
+
return CArray[self.element_type.qmod_type] # type:ignore[name-defined]
|
115
125
|
|
116
126
|
|
117
127
|
class Pauli(ClassicalType):
|
@@ -126,8 +136,8 @@ class Pauli(ClassicalType):
|
|
126
136
|
return values_with_discriminator(values, "kind", "pauli")
|
127
137
|
|
128
138
|
@property
|
129
|
-
def
|
130
|
-
return
|
139
|
+
def qmod_type(self) -> type:
|
140
|
+
return PauliEnum
|
131
141
|
|
132
142
|
|
133
143
|
class StructMetaType(ClassicalType):
|
@@ -142,7 +152,7 @@ class StructMetaType(ClassicalType):
|
|
142
152
|
return values_with_discriminator(values, "kind", "type_proxy")
|
143
153
|
|
144
154
|
|
145
|
-
class
|
155
|
+
class CStructBase: # marker for Qmod structs in the Python SDK
|
146
156
|
pass
|
147
157
|
|
148
158
|
|
@@ -159,8 +169,8 @@ class Struct(ClassicalType):
|
|
159
169
|
return values_with_discriminator(values, "kind", "struct_instance")
|
160
170
|
|
161
171
|
@property
|
162
|
-
def
|
163
|
-
return type(self.name, (
|
172
|
+
def qmod_type(self) -> type:
|
173
|
+
return type(self.name, (CStructBase,), dict())
|
164
174
|
|
165
175
|
|
166
176
|
class ClassicalArray(ClassicalType):
|
@@ -230,8 +240,8 @@ class LadderOperator(ClassicalType):
|
|
230
240
|
return values_with_discriminator(values, "kind", "ladder_operator")
|
231
241
|
|
232
242
|
@property
|
233
|
-
def
|
234
|
-
return
|
243
|
+
def qmod_type(self) -> type:
|
244
|
+
return LadderOperatorEnum
|
235
245
|
|
236
246
|
|
237
247
|
ConcreteClassicalType = Annotated[
|
@@ -2,12 +2,12 @@ import abc
|
|
2
2
|
from typing import Dict
|
3
3
|
|
4
4
|
import pydantic
|
5
|
-
from pydantic.main import BaseModel
|
6
5
|
|
6
|
+
from classiq.interface.ast_node import ASTNode
|
7
7
|
from classiq.interface.generator.functions.classical_type import ConcreteClassicalType
|
8
8
|
|
9
9
|
|
10
|
-
class FunctionDeclaration(
|
10
|
+
class FunctionDeclaration(ASTNode, abc.ABC):
|
11
11
|
"""
|
12
12
|
Facilitates the creation of a common function interface object.
|
13
13
|
"""
|
@@ -1,6 +1,12 @@
|
|
1
|
+
from typing import Any, Union
|
2
|
+
|
1
3
|
import pydantic
|
2
4
|
|
3
|
-
from classiq.interface.chemistry.ground_state_problem import
|
5
|
+
from classiq.interface.chemistry.ground_state_problem import (
|
6
|
+
CHEMISTRY_PROBLEMS,
|
7
|
+
HamiltonianProblem,
|
8
|
+
MoleculeProblem,
|
9
|
+
)
|
4
10
|
from classiq.interface.generator.chemistry_function_params import (
|
5
11
|
ChemistryFunctionParams,
|
6
12
|
)
|
@@ -10,7 +16,9 @@ from classiq.exceptions import ClassiqValueError
|
|
10
16
|
|
11
17
|
class HartreeFock(ChemistryFunctionParams):
|
12
18
|
@pydantic.validator("gs_problem")
|
13
|
-
def validate_gs_problem(
|
19
|
+
def validate_gs_problem(
|
20
|
+
cls, gs_problem: Any
|
21
|
+
) -> Union[MoleculeProblem, HamiltonianProblem]:
|
14
22
|
if not isinstance(gs_problem, CHEMISTRY_PROBLEMS):
|
15
23
|
raise ClassiqValueError(
|
16
24
|
f"ground state problem must be of type {CHEMISTRY_PROBLEMS}"
|
@@ -26,10 +26,10 @@ from classiq.interface.generator.types.struct_declaration import StructDeclarati
|
|
26
26
|
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
27
27
|
from classiq.interface.helpers.validation_helpers import is_list_unique
|
28
28
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
29
|
+
from classiq.interface.model.quantum_register import QReg, QRegGenericAlias
|
29
30
|
|
30
31
|
from classiq import ForeignFunctionDefinition as SynthesisForeignFunctionDefinition
|
31
32
|
from classiq.exceptions import ClassiqValueError
|
32
|
-
from classiq.quantum_register import QReg, QRegGenericAlias
|
33
33
|
|
34
34
|
MAIN_FUNCTION_NAME = "main"
|
35
35
|
CLASSICAL_ENTRY_FUNCTION_NAME = "cmain"
|
@@ -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(
|
@@ -2,15 +2,13 @@ from typing import Any, ClassVar, Dict, Mapping
|
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
5
|
+
from classiq.interface.ast_node import HashableASTNode
|
5
6
|
from classiq.interface.generator.functions.classical_type import ConcreteClassicalType
|
6
|
-
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
7
|
-
HashablePydanticBaseModel,
|
8
|
-
)
|
9
7
|
|
10
8
|
from classiq.exceptions import ClassiqValueError
|
11
9
|
|
12
10
|
|
13
|
-
class StructDeclaration(
|
11
|
+
class StructDeclaration(HashableASTNode):
|
14
12
|
name: str
|
15
13
|
|
16
14
|
variables: Dict[str, ConcreteClassicalType] = pydantic.Field(
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import dataclasses
|
2
|
-
from typing import Any, List, Mapping
|
2
|
+
from typing import Any, Iterator, List, Mapping
|
3
3
|
|
4
4
|
from sympy import sympify
|
5
5
|
|
@@ -61,8 +61,8 @@ class CallSynthesisData(Mapping):
|
|
61
61
|
def __getitem__(self, key: str) -> Any:
|
62
62
|
return dataclasses.asdict(self)[key]
|
63
63
|
|
64
|
-
def __iter__(self):
|
64
|
+
def __iter__(self) -> Iterator[str]:
|
65
65
|
return iter(dataclasses.asdict(self))
|
66
66
|
|
67
|
-
def __len__(self):
|
67
|
+
def __len__(self) -> int:
|
68
68
|
return len(dataclasses.asdict(self))
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from classiq.interface.generator.expressions.expression import Expression
|
4
|
+
from classiq.interface.model.quantum_statement import QuantumOperation
|
5
|
+
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from classiq.interface.model.statement_block import StatementBlock
|
8
|
+
|
9
|
+
|
10
|
+
class ClassicalIf(QuantumOperation):
|
11
|
+
condition: Expression
|
12
|
+
then: "StatementBlock"
|
13
|
+
else_: "StatementBlock"
|
@@ -1,8 +1,7 @@
|
|
1
|
-
import
|
2
|
-
|
1
|
+
from classiq.interface.ast_node import ASTNode
|
3
2
|
from classiq.interface.generator.functions.classical_type import ConcreteClassicalType
|
4
3
|
|
5
4
|
|
6
|
-
class ClassicalParameterDeclaration(
|
5
|
+
class ClassicalParameterDeclaration(ASTNode):
|
7
6
|
name: str
|
8
7
|
classical_type: ConcreteClassicalType
|
@@ -5,7 +5,10 @@ from sympy import Equality
|
|
5
5
|
from sympy.core.numbers import Integer
|
6
6
|
|
7
7
|
from classiq.interface.generator.expressions.expression import Expression
|
8
|
-
from classiq.interface.generator.expressions.qmod_qscalar_proxy import
|
8
|
+
from classiq.interface.generator.expressions.qmod_qscalar_proxy import (
|
9
|
+
QmodQNumProxy,
|
10
|
+
QmodSizedProxy,
|
11
|
+
)
|
9
12
|
from classiq.interface.model.quantum_expressions.control_state import (
|
10
13
|
min_bit_length,
|
11
14
|
to_twos_complement,
|
@@ -17,18 +20,18 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
17
20
|
from classiq.exceptions import ClassiqValueError
|
18
21
|
|
19
22
|
if TYPE_CHECKING:
|
20
|
-
from classiq.interface.model.
|
23
|
+
from classiq.interface.model.statement_block import StatementBlock
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
"
|
25
|
+
CONTROL_INOUT_NAME = "ctrl"
|
26
|
+
CONTROL_CTRL_ARG_ERROR_MESSAGE_FORMAT = (
|
27
|
+
"control condition must be of the form '<quantum-variable> == "
|
25
28
|
"<classical-integer-expression>', but condition's {}-hand side was {!r}"
|
26
29
|
)
|
27
30
|
|
28
31
|
|
29
|
-
class
|
30
|
-
|
31
|
-
_ctrl: Optional[
|
32
|
+
class Control(QuantumExpressionOperation):
|
33
|
+
body: "StatementBlock"
|
34
|
+
_ctrl: Optional[QmodSizedProxy] = pydantic.PrivateAttr(
|
32
35
|
default=None,
|
33
36
|
)
|
34
37
|
_ctrl_val: Optional[int] = pydantic.PrivateAttr(
|
@@ -40,7 +43,7 @@ class QuantumIfOperation(QuantumExpressionOperation):
|
|
40
43
|
return self.expression
|
41
44
|
|
42
45
|
@property
|
43
|
-
def ctrl(self) ->
|
46
|
+
def ctrl(self) -> QmodSizedProxy:
|
44
47
|
assert self._ctrl is not None
|
45
48
|
return self._ctrl
|
46
49
|
|
@@ -51,44 +54,59 @@ class QuantumIfOperation(QuantumExpressionOperation):
|
|
51
54
|
|
52
55
|
def resolve_condition(self) -> None:
|
53
56
|
condition = self.condition.value.value
|
54
|
-
if
|
57
|
+
if isinstance(condition, QmodSizedProxy):
|
58
|
+
self._resolve_port_condition(condition)
|
59
|
+
elif isinstance(condition, Equality):
|
60
|
+
self._resolve_num_condition(condition)
|
61
|
+
else:
|
55
62
|
raise ClassiqValueError(
|
56
|
-
f"
|
63
|
+
f"control condition must be a qubit, an array of qubits, or a quantum "
|
64
|
+
f"numeric equality, was {str(condition)!r}"
|
57
65
|
)
|
66
|
+
|
67
|
+
def _resolve_port_condition(self, condition: QmodSizedProxy) -> None:
|
68
|
+
self._ctrl = condition
|
69
|
+
|
70
|
+
def _resolve_num_condition(self, condition: Equality) -> None:
|
58
71
|
ctrl, ctrl_val = condition.args
|
59
72
|
if isinstance(ctrl, Integer) and isinstance(ctrl_val, QmodQNumProxy):
|
60
73
|
ctrl, ctrl_val = ctrl_val, ctrl
|
61
74
|
if not isinstance(ctrl, QmodQNumProxy):
|
62
75
|
raise ClassiqValueError(
|
63
|
-
|
76
|
+
CONTROL_CTRL_ARG_ERROR_MESSAGE_FORMAT.format("left", str(ctrl))
|
64
77
|
)
|
65
78
|
if not isinstance(ctrl_val, Integer):
|
66
79
|
raise ClassiqValueError(
|
67
|
-
|
68
|
-
"right", str(ctrl_val)
|
69
|
-
)
|
80
|
+
CONTROL_CTRL_ARG_ERROR_MESSAGE_FORMAT.format("right", str(ctrl_val))
|
70
81
|
)
|
71
82
|
self._ctrl, self._ctrl_val = ctrl, int(ctrl_val)
|
72
83
|
|
84
|
+
@property
|
85
|
+
def has_ctrl_state(self) -> bool:
|
86
|
+
assert self._ctrl is not None
|
87
|
+
return self._ctrl_val is not None
|
88
|
+
|
73
89
|
@property
|
74
90
|
def ctrl_state(self) -> str:
|
75
|
-
|
76
|
-
|
77
|
-
|
91
|
+
ctrl = self.ctrl
|
92
|
+
assert isinstance(ctrl, QmodQNumProxy)
|
93
|
+
is_signed = ctrl.is_signed
|
94
|
+
fraction_places = ctrl.fraction_digits
|
95
|
+
ctrl_size = len(ctrl)
|
78
96
|
if not is_signed and self.ctrl_val < 0:
|
79
97
|
raise ClassiqValueError(
|
80
|
-
f"Variable {str(
|
98
|
+
f"Variable {str(ctrl)!r} is not signed but control value "
|
81
99
|
f"{self.ctrl_val} is negative"
|
82
100
|
)
|
83
101
|
required_qubits = min_bit_length(self.ctrl_val, is_signed)
|
84
102
|
if ctrl_size < required_qubits:
|
85
103
|
raise ClassiqValueError(
|
86
|
-
f"Variable {str(
|
104
|
+
f"Variable {str(ctrl)!r} has {ctrl_size} qubits but control value "
|
87
105
|
f"{str(self.ctrl_val)!r} requires at least {required_qubits} qubits"
|
88
106
|
)
|
89
107
|
if fraction_places != 0:
|
90
108
|
raise ClassiqValueError(
|
91
|
-
f"
|
109
|
+
f"Comparison (`==`) on a non-integer quantum variable {str(ctrl)!r} is "
|
92
110
|
f"not supported at the moment"
|
93
111
|
)
|
94
112
|
return to_twos_complement(self.ctrl_val, ctrl_size, is_signed)
|
@@ -1,9 +1,10 @@
|
|
1
|
-
from pydantic import
|
1
|
+
from pydantic import Extra
|
2
2
|
|
3
|
+
from classiq.interface.ast_node import ASTNode
|
3
4
|
from classiq.interface.generator.expressions.expression import Expression
|
4
5
|
|
5
6
|
|
6
|
-
class HandleBinding(
|
7
|
+
class HandleBinding(ASTNode):
|
7
8
|
name: str
|
8
9
|
|
9
10
|
class Config:
|
@@ -0,0 +1,10 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from classiq.interface.model.quantum_statement import QuantumOperation
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
from classiq.interface.model.statement_block import StatementBlock
|
7
|
+
|
8
|
+
|
9
|
+
class Invert(QuantumOperation):
|
10
|
+
body: "StatementBlock"
|
classiq/interface/model/model.py
CHANGED
@@ -3,6 +3,7 @@ from typing import Any, Dict, List, Literal, NewType, Optional, Set
|
|
3
3
|
|
4
4
|
import pydantic
|
5
5
|
|
6
|
+
from classiq.interface.ast_node import ASTNode
|
6
7
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
7
8
|
from classiq.interface.generator.constant import Constant
|
8
9
|
from classiq.interface.generator.functions.port_declaration import (
|
@@ -51,7 +52,7 @@ class VersionedSerializedModel(VersionedModel):
|
|
51
52
|
model: SerializedModel
|
52
53
|
|
53
54
|
|
54
|
-
class Model(VersionedModel):
|
55
|
+
class Model(VersionedModel, ASTNode):
|
55
56
|
"""
|
56
57
|
All the relevant data for generating quantum circuit in one place.
|
57
58
|
"""
|
@@ -0,0 +1,12 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from classiq.interface.generator.expressions.expression import Expression
|
4
|
+
from classiq.interface.model.quantum_statement import QuantumOperation
|
5
|
+
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from classiq.interface.model.statement_block import StatementBlock
|
8
|
+
|
9
|
+
|
10
|
+
class Power(QuantumOperation):
|
11
|
+
power: Expression
|
12
|
+
body: "StatementBlock"
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import itertools
|
2
2
|
import re
|
3
|
-
from typing import Any, Dict, List, Mapping, Optional, Set, Union
|
3
|
+
from typing import Any, Dict, List, Mapping, Optional, Set, Type, Union
|
4
4
|
|
5
5
|
import pydantic
|
6
|
-
from pydantic import BaseModel
|
7
6
|
|
7
|
+
from classiq.interface.ast_node import ASTNode
|
8
8
|
from classiq.interface.generator.expressions.expression import Expression
|
9
9
|
from classiq.interface.generator.functions.function_declaration import (
|
10
10
|
FunctionDeclaration,
|
@@ -77,8 +77,13 @@ def _validate_no_duplicated_handles(
|
|
77
77
|
def _validate_no_mixing_sliced_and_whole_handles(
|
78
78
|
inouts: Mapping[str, HandleBinding],
|
79
79
|
) -> None:
|
80
|
+
def _treat_subscript_as_slice(type_: Type[HandleBinding]) -> Type[HandleBinding]:
|
81
|
+
if type_ == SubscriptHandleBinding:
|
82
|
+
return SlicedHandleBinding
|
83
|
+
return type_
|
84
|
+
|
80
85
|
inout_handle_names_to_types = {
|
81
|
-
handle_name: {type(handle) for handle in handles}
|
86
|
+
handle_name: {_treat_subscript_as_slice(type(handle)) for handle in handles}
|
82
87
|
for handle_name, handles in itertools.groupby(
|
83
88
|
inouts.values(), lambda handle: handle.name
|
84
89
|
)
|
@@ -103,7 +108,7 @@ ArgValue = Union[
|
|
103
108
|
]
|
104
109
|
|
105
110
|
|
106
|
-
class OperandIdentifier(
|
111
|
+
class OperandIdentifier(ASTNode):
|
107
112
|
name: str
|
108
113
|
index: Expression
|
109
114
|
|
@@ -1,21 +1,18 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Dict, List, Optional, Union
|
2
2
|
|
3
3
|
import pydantic
|
4
|
-
from pydantic import BaseModel
|
5
4
|
|
5
|
+
from classiq.interface.ast_node import ASTNode
|
6
6
|
from classiq.interface.generator.expressions.expression import Expression
|
7
7
|
from classiq.interface.model.quantum_function_declaration import (
|
8
8
|
QuantumOperandDeclaration,
|
9
9
|
)
|
10
|
-
from classiq.interface.model.quantum_if_operation import QuantumIfOperation
|
11
10
|
|
12
11
|
if TYPE_CHECKING:
|
13
12
|
from classiq.interface.model.statement_block import StatementBlock
|
14
13
|
|
15
|
-
from classiq.interface.model.within_apply_operation import WithinApplyOperation
|
16
14
|
|
17
|
-
|
18
|
-
class QuantumLambdaFunction(BaseModel):
|
15
|
+
class QuantumLambdaFunction(ASTNode):
|
19
16
|
"""
|
20
17
|
The definition of an anonymous function passed as operand to higher-level functions
|
21
18
|
"""
|
@@ -39,7 +36,7 @@ class QuantumLambdaFunction(BaseModel):
|
|
39
36
|
self._func_decl = fd
|
40
37
|
|
41
38
|
|
42
|
-
class LambdaListComprehension(
|
39
|
+
class LambdaListComprehension(ASTNode):
|
43
40
|
"""
|
44
41
|
Specification of a list of lambda functions iteratively
|
45
42
|
"""
|
@@ -59,6 +56,3 @@ class LambdaListComprehension(BaseModel):
|
|
59
56
|
|
60
57
|
QuantumCallable = Union[str, QuantumLambdaFunction]
|
61
58
|
QuantumOperand = Union[QuantumCallable, List[QuantumCallable], LambdaListComprehension]
|
62
|
-
|
63
|
-
QuantumIfOperation.update_forward_refs(QuantumOperand=QuantumOperand)
|
64
|
-
WithinApplyOperation.update_forward_refs(QuantumOperand=QuantumOperand)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
from typing import Mapping, Union
|
2
2
|
|
3
|
-
from pydantic import
|
3
|
+
from pydantic import Extra
|
4
4
|
|
5
|
+
from classiq.interface.ast_node import ASTNode
|
5
6
|
from classiq.interface.model.handle_binding import (
|
6
7
|
HandleBinding,
|
7
8
|
SlicedHandleBinding,
|
@@ -9,7 +10,7 @@ from classiq.interface.model.handle_binding import (
|
|
9
10
|
)
|
10
11
|
|
11
12
|
|
12
|
-
class QuantumStatement(
|
13
|
+
class QuantumStatement(ASTNode):
|
13
14
|
class Config:
|
14
15
|
extra = Extra.forbid
|
15
16
|
|
@@ -4,25 +4,24 @@ import pydantic
|
|
4
4
|
from pydantic import Extra, Field
|
5
5
|
from typing_extensions import Annotated
|
6
6
|
|
7
|
+
from classiq.interface.ast_node import HashableASTNode
|
7
8
|
from classiq.interface.generator.arith.register_user_input import (
|
8
9
|
RegisterArithmeticInfo,
|
9
10
|
RegisterUserInput,
|
10
11
|
)
|
11
12
|
from classiq.interface.generator.expressions.expression import Expression
|
13
|
+
from classiq.interface.generator.expressions.qmod_qarray_proxy import QmodQArrayProxy
|
12
14
|
from classiq.interface.generator.expressions.qmod_qscalar_proxy import (
|
13
15
|
QmodQNumProxy,
|
14
16
|
QmodQScalarProxy,
|
15
17
|
)
|
16
18
|
from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
|
17
|
-
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
18
|
-
HashablePydanticBaseModel,
|
19
|
-
)
|
20
19
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
21
20
|
|
22
21
|
from classiq.exceptions import ClassiqValueError
|
23
22
|
|
24
23
|
|
25
|
-
class QuantumType(
|
24
|
+
class QuantumType(HashableASTNode):
|
26
25
|
class Config:
|
27
26
|
extra = Extra.forbid
|
28
27
|
|
@@ -67,12 +66,9 @@ class QuantumBit(QuantumScalar):
|
|
67
66
|
return values_with_discriminator(values, "kind", "qbit")
|
68
67
|
|
69
68
|
|
70
|
-
class
|
71
|
-
length: Optional[Expression]
|
72
|
-
|
73
|
-
|
74
|
-
class QuantumBitvector(QuantumArray):
|
69
|
+
class QuantumBitvector(QuantumType):
|
75
70
|
kind: Literal["qvec"]
|
71
|
+
length: Optional[Expression]
|
76
72
|
|
77
73
|
@pydantic.root_validator(pre=True)
|
78
74
|
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
@@ -82,6 +78,9 @@ class QuantumBitvector(QuantumArray):
|
|
82
78
|
if self.length is not None and self.length.is_evaluated():
|
83
79
|
self._size_in_bits = self.length.to_int_value()
|
84
80
|
|
81
|
+
def get_proxy(self, name: str) -> QmodQArrayProxy:
|
82
|
+
return QmodQArrayProxy(name, self.size_in_bits)
|
83
|
+
|
85
84
|
|
86
85
|
class QuantumNumeric(QuantumScalar):
|
87
86
|
kind: Literal["qnum"]
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from typing import Any, Mapping, Optional
|
2
2
|
|
3
3
|
import pydantic
|
4
|
-
from pydantic import BaseModel
|
5
4
|
|
5
|
+
from classiq.interface.ast_node import ASTNode
|
6
6
|
from classiq.interface.generator.expressions.expression import Expression
|
7
7
|
from classiq.interface.model.quantum_type import (
|
8
8
|
ConcreteQuantumType,
|
@@ -11,7 +11,7 @@ from classiq.interface.model.quantum_type import (
|
|
11
11
|
)
|
12
12
|
|
13
13
|
|
14
|
-
class QuantumVariableDeclaration(
|
14
|
+
class QuantumVariableDeclaration(ASTNode):
|
15
15
|
name: str
|
16
16
|
quantum_type: ConcreteQuantumType
|
17
17
|
size: Optional[Expression] = pydantic.Field(default=None)
|