classiq 0.42.2__py3-none-any.whl → 0.43.1__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 +2 -6
- classiq/_internals/api_wrapper.py +6 -12
- classiq/_internals/authentication/token_manager.py +5 -2
- classiq/_internals/jobs.py +5 -10
- classiq/analyzer/rb.py +3 -3
- classiq/applications/chemistry/chemistry_model_constructor.py +12 -8
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +2 -2
- classiq/applications/finance/finance_model_constructor.py +16 -13
- classiq/applications/qsvm/__init__.py +1 -3
- classiq/applications/qsvm/qsvm_model_constructor.py +7 -6
- classiq/exceptions.py +9 -4
- classiq/execution/execution_session.py +5 -2
- classiq/execution/qnn.py +1 -1
- classiq/executor.py +0 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/chemistry/operator.py +19 -5
- classiq/interface/executor/constants.py +1 -0
- classiq/interface/finance/function_input.py +16 -10
- classiq/interface/generator/application_apis/chemistry_declarations.py +2 -2
- classiq/interface/generator/application_apis/qsvm_declarations.py +4 -2
- classiq/interface/generator/arith/argument_utils.py +20 -3
- classiq/interface/generator/arith/arithmetic_expression_validator.py +3 -26
- classiq/interface/generator/arith/binary_ops.py +8 -14
- classiq/interface/generator/arith/extremum_operations.py +30 -0
- classiq/interface/generator/arith/number_utils.py +1 -1
- classiq/interface/generator/arith/unary_ops.py +1 -3
- classiq/interface/generator/compiler_keywords.py +1 -1
- classiq/interface/generator/expressions/atomic_expression_functions.py +13 -3
- classiq/interface/generator/expressions/enums/__init__.py +0 -20
- classiq/interface/generator/expressions/enums/finance_functions.py +11 -18
- classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +52 -37
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +16 -11
- classiq/interface/generator/expressions/qmod_sized_proxy.py +5 -5
- classiq/interface/generator/function_param_list_without_self_reference.py +0 -10
- classiq/interface/generator/function_params.py +0 -4
- classiq/interface/generator/functions/__init__.py +0 -20
- classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +2 -2
- classiq/interface/generator/functions/builtins/open_lib_functions.py +530 -1
- classiq/interface/generator/functions/classical_type.py +22 -69
- classiq/interface/generator/functions/port_declaration.py +0 -11
- classiq/interface/generator/model/__init__.py +0 -1
- classiq/interface/generator/model/model.py +9 -185
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +3 -1
- classiq/interface/generator/types/builtin_enum_declarations.py +69 -0
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +2 -2
- classiq/interface/generator/types/enum_declaration.py +57 -0
- classiq/interface/jobs.py +36 -65
- classiq/interface/model/bind_operation.py +3 -0
- classiq/interface/model/classical_parameter_declaration.py +3 -0
- classiq/interface/model/handle_binding.py +7 -0
- classiq/interface/model/inplace_binary_operation.py +13 -15
- classiq/interface/model/model.py +8 -20
- classiq/interface/model/native_function_definition.py +0 -17
- classiq/interface/model/quantum_function_call.py +63 -182
- classiq/interface/model/quantum_type.py +71 -10
- classiq/interface/server/routes.py +0 -6
- classiq/qmod/__init__.py +3 -3
- classiq/qmod/builtins/__init__.py +10 -1
- classiq/qmod/builtins/classical_execution_primitives.py +4 -2
- classiq/qmod/builtins/enums.py +177 -0
- classiq/qmod/builtins/functions.py +1 -2
- classiq/qmod/builtins/operations.py +2 -4
- classiq/qmod/builtins/structs.py +16 -17
- classiq/qmod/declaration_inferrer.py +23 -20
- classiq/qmod/model_state_container.py +2 -0
- classiq/qmod/native/pretty_printer.py +31 -13
- classiq/qmod/pretty_print/pretty_printer.py +52 -27
- classiq/qmod/qmod_constant.py +7 -3
- classiq/qmod/qmod_parameter.py +2 -1
- classiq/qmod/qmod_struct.py +9 -33
- classiq/qmod/qmod_variable.py +55 -22
- classiq/qmod/quantum_callable.py +6 -1
- classiq/qmod/quantum_expandable.py +29 -11
- classiq/qmod/quantum_function.py +8 -4
- classiq/qmod/semantics/annotation.py +38 -0
- classiq/qmod/semantics/error_manager.py +49 -0
- classiq/qmod/semantics/static_semantics_visitor.py +308 -0
- classiq/qmod/semantics/validation/func_call_validation.py +149 -0
- classiq/qmod/semantics/validation/types_validation.py +21 -0
- classiq/qmod/symbolic.py +6 -6
- classiq/qmod/symbolic_expr.py +26 -11
- classiq/qmod/utilities.py +23 -1
- {classiq-0.42.2.dist-info → classiq-0.43.1.dist-info}/METADATA +2 -2
- {classiq-0.42.2.dist-info → classiq-0.43.1.dist-info}/RECORD +88 -103
- classiq/_internals/_qfunc_ext.py +0 -6
- classiq/applications/libraries/ampltitude_estimation_library.py +0 -11
- classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
- classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
- classiq/interface/generator/expressions/enums/chemistry.py +0 -28
- classiq/interface/generator/expressions/enums/classical_enum.py +0 -20
- classiq/interface/generator/expressions/enums/ladder_operator.py +0 -6
- classiq/interface/generator/expressions/enums/optimizers.py +0 -9
- classiq/interface/generator/expressions/enums/pauli.py +0 -8
- classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
- classiq/interface/generator/functions/foreign_function_definition.py +0 -114
- classiq/interface/generator/functions/function_implementation.py +0 -107
- classiq/interface/generator/functions/native_function_definition.py +0 -155
- classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
- classiq/interface/generator/functions/register.py +0 -44
- classiq/interface/generator/functions/register_mapping_data.py +0 -106
- classiq/interface/generator/inequality_mixer.py +0 -51
- classiq/interface/generator/model/classical_main_validator.py +0 -106
- classiq/interface/generator/range_mixer.py +0 -56
- classiq/interface/generator/state_propagator.py +0 -74
- classiq/interface/model/resolvers/function_call_resolver.py +0 -64
- classiq/interface/model/validations/__init__.py +0 -0
- classiq/interface/model/validations/handle_validation_base.py +0 -55
- classiq/interface/model/validations/handles_validator.py +0 -153
- classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
- /classiq/{interface/generator/credit_risk_example → qmod/semantics}/__init__.py +0 -0
- /classiq/{interface/model/resolvers → qmod/semantics/validation}/__init__.py +0 -0
- {classiq-0.42.2.dist-info → classiq-0.43.1.dist-info}/WHEEL +0 -0
@@ -1,10 +1,9 @@
|
|
1
1
|
import ast
|
2
|
-
import builtins
|
3
2
|
import re
|
4
3
|
from _ast import AST
|
5
|
-
from typing import Any, Optional, Set, Tuple, Type, Union
|
4
|
+
from typing import Any, Dict, Optional, Set, Tuple, Type, Union
|
6
5
|
|
7
|
-
from typing_extensions import get_args
|
6
|
+
from typing_extensions import TypeAlias, get_args
|
8
7
|
|
9
8
|
from classiq.interface.generator.arith.ast_node_rewrite import AstNodeRewrite
|
10
9
|
from classiq.interface.generator.expressions.sympy_supported_expressions import (
|
@@ -21,6 +20,7 @@ IDENITIFIER_REGEX = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*")
|
|
21
20
|
_REPEATED_VARIABLES_ERROR_MESSAGE: str = (
|
22
21
|
"Repeated variables in the beginning of an arithmetic expression are not allowed."
|
23
22
|
)
|
23
|
+
ValidKeyValuePairs: TypeAlias = Dict[str, Set[str]]
|
24
24
|
|
25
25
|
SupportedNodesTypes = Union[
|
26
26
|
ast.Expression,
|
@@ -64,14 +64,12 @@ class ExpressionValidator(ast.NodeVisitor):
|
|
64
64
|
supported_nodes: Tuple[Type[AST], ...],
|
65
65
|
expression_type: str = DEFAULT_EXPRESSION_TYPE,
|
66
66
|
supported_functions: Optional[Set[str]] = None,
|
67
|
-
supported_attr_values: Optional[Set[str]] = None,
|
68
67
|
mode: str = "eval",
|
69
68
|
) -> None:
|
70
69
|
super().__init__()
|
71
70
|
self.supported_nodes = supported_nodes
|
72
71
|
self._expression_type = expression_type
|
73
72
|
self._supported_functions = supported_functions or DEFAULT_SUPPORTED_FUNC_NAMES
|
74
|
-
self._supported_attr_values = supported_attr_values or set()
|
75
73
|
self._mode = mode
|
76
74
|
self._ast_obj: Optional[ast.AST] = None
|
77
75
|
|
@@ -170,26 +168,7 @@ class ExpressionValidator(ast.NodeVisitor):
|
|
170
168
|
self.validate_Constant(node)
|
171
169
|
self.generic_visit(node)
|
172
170
|
|
173
|
-
def validate_Attribute(self, node: ast.Attribute) -> None: # noqa: N802
|
174
|
-
if not (
|
175
|
-
isinstance(node.value, ast.Name)
|
176
|
-
and node.value.id in self._supported_attr_values
|
177
|
-
):
|
178
|
-
raise ClassiqValueError(
|
179
|
-
f"Attribute is not supported for value {node.value}"
|
180
|
-
)
|
181
|
-
|
182
171
|
def visit_Attribute(self, node: ast.Attribute) -> None:
|
183
|
-
self.validate_Attribute(node)
|
184
|
-
self.generic_visit(node)
|
185
|
-
|
186
|
-
def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:
|
187
|
-
if self._mode == "exec":
|
188
|
-
if hasattr(builtins, node.name):
|
189
|
-
raise ClassiqValueError(
|
190
|
-
f"Defining a function named {node.name} is forbidden"
|
191
|
-
)
|
192
|
-
self._supported_functions.add(node.name)
|
193
172
|
self.generic_visit(node)
|
194
173
|
|
195
174
|
@classmethod
|
@@ -203,7 +182,6 @@ def validate_expression(
|
|
203
182
|
supported_nodes: Tuple[Type[AST], ...] = DEFAULT_SUPPORTED_NODE_TYPES,
|
204
183
|
expression_type: str = DEFAULT_EXPRESSION_TYPE,
|
205
184
|
supported_functions: Optional[Set[str]] = None,
|
206
|
-
supported_attr_values: Optional[Set[str]] = None,
|
207
185
|
mode: str = "eval",
|
208
186
|
) -> ast.AST:
|
209
187
|
supported_functions = supported_functions or set(SYMPY_SUPPORTED_EXPRESSIONS).union(
|
@@ -213,7 +191,6 @@ def validate_expression(
|
|
213
191
|
supported_nodes,
|
214
192
|
expression_type,
|
215
193
|
supported_functions,
|
216
|
-
supported_attr_values,
|
217
194
|
mode,
|
218
195
|
)
|
219
196
|
validator.validate(expression)
|
@@ -264,10 +264,10 @@ class Adder(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
|
264
264
|
|
265
265
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
266
266
|
left_arg = argument_utils.limit_fraction_places(
|
267
|
-
self.left_arg,
|
267
|
+
self.left_arg, self.machine_precision
|
268
268
|
)
|
269
269
|
right_arg = argument_utils.limit_fraction_places(
|
270
|
-
self.right_arg,
|
270
|
+
self.right_arg, self.machine_precision
|
271
271
|
)
|
272
272
|
lb = argument_utils.lower_bound(left_arg) + argument_utils.lower_bound(
|
273
273
|
right_arg
|
@@ -305,9 +305,7 @@ class Subtractor(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
|
305
305
|
def _get_effective_arg(
|
306
306
|
arg: RegisterOrConst, machine_precision: int
|
307
307
|
) -> RegisterOrConst:
|
308
|
-
return argument_utils.limit_fraction_places(
|
309
|
-
arg, machine_precision=machine_precision
|
310
|
-
)
|
308
|
+
return argument_utils.limit_fraction_places(arg, machine_precision)
|
311
309
|
|
312
310
|
@property
|
313
311
|
def effective_left_arg(self) -> RegisterOrConst:
|
@@ -453,13 +451,9 @@ class Multiplier(BinaryOpWithFloatInputs):
|
|
453
451
|
|
454
452
|
def expected_fraction_places(self) -> int:
|
455
453
|
return argument_utils.fraction_places(
|
456
|
-
argument_utils.limit_fraction_places(
|
457
|
-
self.left_arg, machine_precision=self.machine_precision
|
458
|
-
)
|
454
|
+
argument_utils.limit_fraction_places(self.left_arg, self.machine_precision)
|
459
455
|
) + argument_utils.fraction_places(
|
460
|
-
argument_utils.limit_fraction_places(
|
461
|
-
self.right_arg, machine_precision=self.machine_precision
|
462
|
-
)
|
456
|
+
argument_utils.limit_fraction_places(self.right_arg, self.machine_precision)
|
463
457
|
)
|
464
458
|
|
465
459
|
@staticmethod
|
@@ -483,10 +477,10 @@ class Multiplier(BinaryOpWithFloatInputs):
|
|
483
477
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
484
478
|
fraction_places = min(self.machine_precision, self.expected_fraction_places())
|
485
479
|
left_arg = argument_utils.limit_fraction_places(
|
486
|
-
self.left_arg,
|
480
|
+
self.left_arg, self.machine_precision
|
487
481
|
)
|
488
482
|
right_arg = argument_utils.limit_fraction_places(
|
489
|
-
self.right_arg,
|
483
|
+
self.right_arg, self.machine_precision
|
490
484
|
)
|
491
485
|
bounds = self._get_bounds((left_arg, right_arg), self.machine_precision)
|
492
486
|
|
@@ -572,7 +566,7 @@ class Power(BinaryOpParams[RegisterArithmeticInfo, pydantic.PositiveInt]):
|
|
572
566
|
return (
|
573
567
|
argument_utils.fraction_places(
|
574
568
|
argument_utils.limit_fraction_places(
|
575
|
-
self.left_arg,
|
569
|
+
self.left_arg, self.machine_precision
|
576
570
|
)
|
577
571
|
)
|
578
572
|
* self.right_arg
|
@@ -57,7 +57,21 @@ class Extremum(ArithmeticOperationParams):
|
|
57
57
|
def _bound_calculator(cls, arg1: float, arg2: float) -> float:
|
58
58
|
pass
|
59
59
|
|
60
|
+
@classmethod
|
61
|
+
@abc.abstractmethod
|
62
|
+
def _preferred_arg(
|
63
|
+
cls, arg1: RegisterOrConst, arg2: RegisterOrConst
|
64
|
+
) -> RegisterOrConst:
|
65
|
+
pass
|
66
|
+
|
60
67
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
68
|
+
if argument_utils.arg_bounds_overlap((self.left_arg, self.right_arg)):
|
69
|
+
return self._get_general_case_result_register()
|
70
|
+
return argument_utils.as_arithmetic_info(
|
71
|
+
self._preferred_arg(self.left_arg, self.right_arg)
|
72
|
+
)
|
73
|
+
|
74
|
+
def _get_general_case_result_register(self) -> RegisterArithmeticInfo:
|
61
75
|
integer_part_size = max(
|
62
76
|
argument_utils.integer_part_size(self.left_arg),
|
63
77
|
argument_utils.integer_part_size(self.right_arg),
|
@@ -92,6 +106,14 @@ class Min(Extremum):
|
|
92
106
|
def _bound_calculator(cls, arg1: float, arg2: float) -> float:
|
93
107
|
return min(arg1, arg2)
|
94
108
|
|
109
|
+
@classmethod
|
110
|
+
def _preferred_arg(
|
111
|
+
cls, arg1: RegisterOrConst, arg2: RegisterOrConst
|
112
|
+
) -> RegisterOrConst:
|
113
|
+
if min(argument_utils.bounds(arg1)) < min(argument_utils.bounds(arg2)):
|
114
|
+
return arg1
|
115
|
+
return arg2
|
116
|
+
|
95
117
|
|
96
118
|
class Max(Extremum):
|
97
119
|
output_name = "max_value"
|
@@ -99,3 +121,11 @@ class Max(Extremum):
|
|
99
121
|
@classmethod
|
100
122
|
def _bound_calculator(cls, arg1: float, arg2: float) -> float:
|
101
123
|
return max(arg1, arg2)
|
124
|
+
|
125
|
+
@classmethod
|
126
|
+
def _preferred_arg(
|
127
|
+
cls, arg1: RegisterOrConst, arg2: RegisterOrConst
|
128
|
+
) -> RegisterOrConst:
|
129
|
+
if max(argument_utils.bounds(arg1)) > max(argument_utils.bounds(arg2)):
|
130
|
+
return arg1
|
131
|
+
return arg2
|
@@ -100,7 +100,7 @@ def bounds_to_integer_part_size(lb: float, ub: float) -> int:
|
|
100
100
|
)
|
101
101
|
|
102
102
|
|
103
|
-
def limit_fraction_places(number: float,
|
103
|
+
def limit_fraction_places(number: float, machine_precision: int) -> float:
|
104
104
|
orig_bin_rep = binary_string(number)[::-1]
|
105
105
|
orig_fractions = fraction_places(number)
|
106
106
|
|
@@ -64,9 +64,7 @@ class BitwiseInvert(UnaryOpParams):
|
|
64
64
|
output_name = "inverted"
|
65
65
|
|
66
66
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
67
|
-
eff_arg = argument_utils.limit_fraction_places(
|
68
|
-
self.arg, machine_precision=self.machine_precision
|
69
|
-
)
|
67
|
+
eff_arg = argument_utils.limit_fraction_places(self.arg, self.machine_precision)
|
70
68
|
if TYPE_CHECKING:
|
71
69
|
assert isinstance(eff_arg, RegisterArithmeticInfo)
|
72
70
|
return RegisterArithmeticInfo(
|
@@ -1,8 +1,10 @@
|
|
1
1
|
from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
|
2
2
|
|
3
|
-
|
3
|
+
SUPPORTED_PYTHON_BUILTIN_FUNCTIONS = {"len", "sum", "print"}
|
4
4
|
|
5
|
-
|
5
|
+
SUPPORTED_CLASSIQ_BUILTIN_FUNCTIONS = {
|
6
|
+
"do_div",
|
7
|
+
"do_slice",
|
6
8
|
"do_subscript",
|
7
9
|
"hypercube_entangler_graph",
|
8
10
|
"grid_entangler_graph",
|
@@ -15,11 +17,19 @@ SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS = {
|
|
15
17
|
"molecule_problem_to_hamiltonian",
|
16
18
|
"fock_hamiltonian_problem_to_hamiltonian",
|
17
19
|
"molecule_ground_state_solution_post_process",
|
20
|
+
}
|
21
|
+
|
22
|
+
SUPPORTED_CLASSIQ_SYMPY_WRAPPERS = {
|
18
23
|
"BitwiseAnd",
|
19
24
|
"BitwiseXor",
|
20
25
|
"BitwiseNot",
|
21
26
|
"BitwiseOr",
|
22
|
-
|
27
|
+
}
|
28
|
+
|
29
|
+
SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS = {
|
30
|
+
*SUPPORTED_CLASSIQ_BUILTIN_FUNCTIONS,
|
31
|
+
*SUPPORTED_CLASSIQ_SYMPY_WRAPPERS,
|
32
|
+
*SUPPORTED_PYTHON_BUILTIN_FUNCTIONS,
|
23
33
|
}
|
24
34
|
|
25
35
|
SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS_QMOD = (
|
@@ -1,20 +0,0 @@
|
|
1
|
-
from enum import EnumMeta
|
2
|
-
|
3
|
-
from .chemistry import Element, FermionMapping
|
4
|
-
from .finance_functions import FinanceFunctionType
|
5
|
-
from .ladder_operator import LadderOperator
|
6
|
-
from .optimizers import Optimizer
|
7
|
-
from .pauli import Pauli
|
8
|
-
from .qsvm_feature_map_entanglement import QSVMFeatureMapEntanglement
|
9
|
-
|
10
|
-
BUILTIN_ENUMS = dict(filter(lambda pair: isinstance(pair[1], EnumMeta), vars().items()))
|
11
|
-
|
12
|
-
__all__ = [
|
13
|
-
"Element",
|
14
|
-
"FermionMapping",
|
15
|
-
"FinanceFunctionType",
|
16
|
-
"LadderOperator",
|
17
|
-
"Optimizer",
|
18
|
-
"Pauli",
|
19
|
-
"QSVMFeatureMapEntanglement",
|
20
|
-
]
|
@@ -1,22 +1,15 @@
|
|
1
|
-
from typing import Dict
|
1
|
+
from typing import TYPE_CHECKING, Dict
|
2
2
|
|
3
|
-
|
3
|
+
if TYPE_CHECKING:
|
4
|
+
from classiq.qmod.builtins.enums import FinanceFunctionType
|
4
5
|
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
SHORTFALL = 1
|
9
|
-
X_SQUARE = 2
|
10
|
-
EUROPEAN_CALL_OPTION = 3
|
7
|
+
def get_finance_function_dict() -> Dict[str, "FinanceFunctionType"]:
|
8
|
+
from classiq.qmod.builtins.enums import FinanceFunctionType
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
"var": FinanceFunctionType.VAR,
|
19
|
-
"expected shortfall": FinanceFunctionType.SHORTFALL,
|
20
|
-
"x**2": FinanceFunctionType.X_SQUARE,
|
21
|
-
"european call option": FinanceFunctionType.EUROPEAN_CALL_OPTION,
|
22
|
-
}
|
10
|
+
return {
|
11
|
+
"var": FinanceFunctionType.VAR,
|
12
|
+
"expected shortfall": FinanceFunctionType.SHORTFALL,
|
13
|
+
"x**2": FinanceFunctionType.X_SQUARE,
|
14
|
+
"european call option": FinanceFunctionType.EUROPEAN_CALL_OPTION,
|
15
|
+
}
|
@@ -0,0 +1,119 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Any, NoReturn
|
4
|
+
|
5
|
+
from classiq.exceptions import ClassiqArithmeticError
|
6
|
+
|
7
|
+
|
8
|
+
class NonSymbolicExpr:
|
9
|
+
@property
|
10
|
+
def type_name(self) -> str:
|
11
|
+
raise NotImplementedError
|
12
|
+
|
13
|
+
@staticmethod
|
14
|
+
def _raise_error(type_name: str, op: str) -> NoReturn:
|
15
|
+
raise ClassiqArithmeticError(
|
16
|
+
f"Unsupported operand type for {op!r}: {type_name}"
|
17
|
+
)
|
18
|
+
|
19
|
+
def __add__(self, other: Any) -> NoReturn:
|
20
|
+
NonSymbolicExpr._raise_error(self.type_name, "+")
|
21
|
+
|
22
|
+
def __sub__(self, other: Any) -> NoReturn:
|
23
|
+
NonSymbolicExpr._raise_error(self.type_name, "-")
|
24
|
+
|
25
|
+
def __mul__(self, other: Any) -> NoReturn:
|
26
|
+
NonSymbolicExpr._raise_error(self.type_name, "*")
|
27
|
+
|
28
|
+
def __truediv__(self, other: Any) -> NoReturn:
|
29
|
+
NonSymbolicExpr._raise_error(self.type_name, "/")
|
30
|
+
|
31
|
+
def __floordiv__(self, other: Any) -> NoReturn:
|
32
|
+
NonSymbolicExpr._raise_error(self.type_name, "//")
|
33
|
+
|
34
|
+
def __mod__(self, other: Any) -> NoReturn:
|
35
|
+
NonSymbolicExpr._raise_error(self.type_name, "%")
|
36
|
+
|
37
|
+
def __pow__(self, other: Any) -> NoReturn:
|
38
|
+
NonSymbolicExpr._raise_error(self.type_name, "**")
|
39
|
+
|
40
|
+
def __lshift__(self, other: Any) -> NoReturn:
|
41
|
+
NonSymbolicExpr._raise_error(self.type_name, "<<")
|
42
|
+
|
43
|
+
def __rshift__(self, other: Any) -> NoReturn:
|
44
|
+
NonSymbolicExpr._raise_error(self.type_name, ">>")
|
45
|
+
|
46
|
+
def __and__(self, other: Any) -> NoReturn:
|
47
|
+
NonSymbolicExpr._raise_error(self.type_name, "&")
|
48
|
+
|
49
|
+
def __xor__(self, other: Any) -> NoReturn:
|
50
|
+
NonSymbolicExpr._raise_error(self.type_name, "^")
|
51
|
+
|
52
|
+
def __or__(self, other: Any) -> NoReturn:
|
53
|
+
NonSymbolicExpr._raise_error(self.type_name, "|")
|
54
|
+
|
55
|
+
def __radd__(self, other: Any) -> NoReturn:
|
56
|
+
NonSymbolicExpr._raise_error(self.type_name, "+")
|
57
|
+
|
58
|
+
def __rsub__(self, other: Any) -> NoReturn:
|
59
|
+
NonSymbolicExpr._raise_error(self.type_name, "-")
|
60
|
+
|
61
|
+
def __rmul__(self, other: Any) -> NoReturn:
|
62
|
+
NonSymbolicExpr._raise_error(self.type_name, "*")
|
63
|
+
|
64
|
+
def __rtruediv__(self, other: Any) -> NoReturn:
|
65
|
+
NonSymbolicExpr._raise_error(self.type_name, "/")
|
66
|
+
|
67
|
+
def __rfloordiv__(self, other: Any) -> NoReturn:
|
68
|
+
NonSymbolicExpr._raise_error(self.type_name, "//")
|
69
|
+
|
70
|
+
def __rmod__(self, other: Any) -> NoReturn:
|
71
|
+
NonSymbolicExpr._raise_error(self.type_name, "%")
|
72
|
+
|
73
|
+
def __rpow__(self, other: Any) -> NoReturn:
|
74
|
+
NonSymbolicExpr._raise_error(self.type_name, "**")
|
75
|
+
|
76
|
+
def __rlshift__(self, other: Any) -> NoReturn:
|
77
|
+
NonSymbolicExpr._raise_error(self.type_name, "<<")
|
78
|
+
|
79
|
+
def __rrshift__(self, other: Any) -> NoReturn:
|
80
|
+
NonSymbolicExpr._raise_error(self.type_name, ">>")
|
81
|
+
|
82
|
+
def __rand__(self, other: Any) -> NoReturn:
|
83
|
+
NonSymbolicExpr._raise_error(self.type_name, "&")
|
84
|
+
|
85
|
+
def __rxor__(self, other: Any) -> NoReturn:
|
86
|
+
NonSymbolicExpr._raise_error(self.type_name, "^")
|
87
|
+
|
88
|
+
def __ror__(self, other: Any) -> NoReturn:
|
89
|
+
NonSymbolicExpr._raise_error(self.type_name, "|")
|
90
|
+
|
91
|
+
def __lt__(self, other: Any) -> NoReturn:
|
92
|
+
NonSymbolicExpr._raise_error(self.type_name, "<")
|
93
|
+
|
94
|
+
def __le__(self, other: Any) -> NoReturn:
|
95
|
+
NonSymbolicExpr._raise_error(self.type_name, "<=")
|
96
|
+
|
97
|
+
def __eq__(self, other: Any) -> NoReturn:
|
98
|
+
NonSymbolicExpr._raise_error(self.type_name, "==")
|
99
|
+
|
100
|
+
def __ne__(self, other: Any) -> NoReturn:
|
101
|
+
NonSymbolicExpr._raise_error(self.type_name, "!=")
|
102
|
+
|
103
|
+
def __gt__(self, other: Any) -> NoReturn:
|
104
|
+
NonSymbolicExpr._raise_error(self.type_name, ">")
|
105
|
+
|
106
|
+
def __ge__(self, other: Any) -> NoReturn:
|
107
|
+
NonSymbolicExpr._raise_error(self.type_name, ">=")
|
108
|
+
|
109
|
+
def __neg__(self) -> NoReturn:
|
110
|
+
NonSymbolicExpr._raise_error(self.type_name, "-")
|
111
|
+
|
112
|
+
def __pos__(self) -> NoReturn:
|
113
|
+
NonSymbolicExpr._raise_error(self.type_name, "+")
|
114
|
+
|
115
|
+
def __abs__(self) -> NoReturn:
|
116
|
+
NonSymbolicExpr._raise_error(self.type_name, "abs")
|
117
|
+
|
118
|
+
def __invert__(self) -> NoReturn:
|
119
|
+
NonSymbolicExpr._raise_error(self.type_name, "~")
|
@@ -1,6 +1,7 @@
|
|
1
|
-
from typing import Any, Mapping, Optional, Tuple, Union
|
1
|
+
from typing import Any, Callable, Mapping, Optional, Tuple, Union
|
2
2
|
|
3
3
|
from classiq.interface.generator.expressions.expression import Expression
|
4
|
+
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
4
5
|
from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
|
5
6
|
from classiq.interface.model.handle_binding import (
|
6
7
|
HandleBinding,
|
@@ -15,22 +16,22 @@ SLICE_OUT_OF_BOUNDS_MSG = "Slice end index out of bounds"
|
|
15
16
|
QARRAY_ELEMENT_NOT_SUBSCRIPTABLE = "Subscripting an element in QArray is illegal"
|
16
17
|
|
17
18
|
|
18
|
-
class QmodQArrayProxy(QmodSizedProxy):
|
19
|
+
class QmodQArrayProxy(NonSymbolicExpr, QmodSizedProxy):
|
19
20
|
def __init__(
|
20
21
|
self,
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
handle: HandleBinding,
|
23
|
+
element_proxy: Callable[[HandleBinding], QmodSizedProxy],
|
24
|
+
element_size: int,
|
25
|
+
length: int,
|
25
26
|
) -> None:
|
26
|
-
super().__init__(
|
27
|
-
self.
|
28
|
-
self.
|
29
|
-
self.
|
27
|
+
super().__init__(handle, element_size * length)
|
28
|
+
self._length = length
|
29
|
+
self._element_proxy = element_proxy
|
30
|
+
self._element_size = element_size
|
30
31
|
|
31
|
-
def __getitem__(self, key: Union[slice, int]) -> "
|
32
|
+
def __getitem__(self, key: Union[slice, int]) -> "QmodSizedProxy":
|
32
33
|
if self._index is not None:
|
33
|
-
raise
|
34
|
+
raise TypeError(QARRAY_ELEMENT_NOT_SUBSCRIPTABLE)
|
34
35
|
|
35
36
|
new_index: Optional[int] = None
|
36
37
|
|
@@ -47,8 +48,14 @@ class QmodQArrayProxy(QmodSizedProxy):
|
|
47
48
|
] > self._size:
|
48
49
|
raise ClassiqValueError(SLICE_OUT_OF_BOUNDS_MSG)
|
49
50
|
|
51
|
+
new_handle = self._get_new_handle(new_index, new_slice)
|
52
|
+
if new_index is not None:
|
53
|
+
return self._element_proxy(new_handle)
|
50
54
|
return QmodQArrayProxy(
|
51
|
-
|
55
|
+
new_handle,
|
56
|
+
self._element_proxy,
|
57
|
+
self._element_size,
|
58
|
+
self._length,
|
52
59
|
)
|
53
60
|
|
54
61
|
def _get_new_slice(self, start: int, end: int) -> Tuple[int, int]:
|
@@ -61,29 +68,34 @@ class QmodQArrayProxy(QmodSizedProxy):
|
|
61
68
|
return "Quantum array"
|
62
69
|
|
63
70
|
@property
|
64
|
-
def
|
65
|
-
|
71
|
+
def _index(self) -> Optional[int]:
|
72
|
+
if not isinstance(self._handle, SubscriptHandleBinding):
|
73
|
+
return None
|
74
|
+
return self._handle.index.to_int_value()
|
66
75
|
|
67
76
|
@property
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
77
|
+
def _slice(self) -> Optional[Tuple[int, int]]:
|
78
|
+
if not isinstance(self._handle, SlicedHandleBinding):
|
79
|
+
return None
|
80
|
+
return self._handle.start.to_int_value(), self._handle.end.to_int_value()
|
81
|
+
|
82
|
+
def _get_new_handle(
|
83
|
+
self, new_index: Optional[int], new_slice: Tuple[int, int]
|
84
|
+
) -> HandleBinding:
|
85
|
+
if new_index is not None:
|
74
86
|
return SubscriptHandleBinding(
|
75
|
-
name=self.
|
76
|
-
index=Expression(expr=str(
|
77
|
-
)
|
78
|
-
|
79
|
-
if self._slice is not None:
|
80
|
-
return SlicedHandleBinding(
|
81
|
-
name=self._name,
|
82
|
-
start=Expression(expr=str(self._slice[0])),
|
83
|
-
end=Expression(expr=str(self._slice[1])),
|
87
|
+
name=self.handle.name,
|
88
|
+
index=Expression(expr=str(new_index)),
|
84
89
|
)
|
90
|
+
return SlicedHandleBinding(
|
91
|
+
name=self.handle.name,
|
92
|
+
start=Expression(expr=str(new_slice[0])),
|
93
|
+
end=Expression(expr=str(new_slice[1])),
|
94
|
+
)
|
85
95
|
|
86
|
-
|
96
|
+
@property
|
97
|
+
def len(self) -> int:
|
98
|
+
return self._length
|
87
99
|
|
88
100
|
@property
|
89
101
|
def fields(self) -> Mapping[str, Any]:
|
@@ -91,12 +103,15 @@ class QmodQArrayProxy(QmodSizedProxy):
|
|
91
103
|
"len": self.len,
|
92
104
|
}
|
93
105
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
106
|
+
@property
|
107
|
+
def size(self) -> int:
|
108
|
+
if (slice_ := self._slice) is not None:
|
109
|
+
length = slice_[1] - slice_[0]
|
110
|
+
elif self._index is not None:
|
111
|
+
length = 1
|
112
|
+
else:
|
113
|
+
length = self._length
|
114
|
+
return length * self._element_size
|
100
115
|
|
101
116
|
def __str__(self) -> str:
|
102
117
|
return str(self.handle)
|
@@ -5,21 +5,21 @@ from sympy import Symbol
|
|
5
5
|
from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
|
6
6
|
from classiq.interface.model.handle_binding import HandleBinding
|
7
7
|
|
8
|
+
from classiq.exceptions import ClassiqValueError
|
8
9
|
|
9
|
-
class QmodQScalarProxy(Symbol, QmodSizedProxy):
|
10
|
-
def __new__(cls, name: str, **assumptions: bool) -> "QmodQScalarProxy":
|
11
|
-
return super().__new__(cls, name, **assumptions)
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
class QmodQScalarProxy(Symbol, QmodSizedProxy):
|
12
|
+
def __new__(cls, handle: HandleBinding, **assumptions: bool) -> "QmodQScalarProxy":
|
13
|
+
return super().__new__(cls, str(handle), **assumptions)
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
return HandleBinding(name=self.name)
|
15
|
+
def __init__(self, handle: HandleBinding, size: int) -> None:
|
16
|
+
super().__init__(handle, size)
|
20
17
|
|
21
18
|
|
22
19
|
class QmodQBitProxy(QmodQScalarProxy):
|
20
|
+
def __init__(self, handle: HandleBinding) -> None:
|
21
|
+
super().__init__(handle, 1)
|
22
|
+
|
23
23
|
@property
|
24
24
|
def type_name(self) -> str:
|
25
25
|
return "Quantum bit"
|
@@ -27,9 +27,14 @@ class QmodQBitProxy(QmodQScalarProxy):
|
|
27
27
|
|
28
28
|
class QmodQNumProxy(QmodQScalarProxy):
|
29
29
|
def __init__(
|
30
|
-
self,
|
30
|
+
self, handle: HandleBinding, size: int, fraction_digits: int, is_signed: bool
|
31
31
|
) -> None:
|
32
|
-
super().__init__(
|
32
|
+
super().__init__(handle, size)
|
33
|
+
if fraction_digits + is_signed > size:
|
34
|
+
raise ClassiqValueError(
|
35
|
+
f"{'Signed' if is_signed else 'Unsigned'} quantum numeric of size "
|
36
|
+
f"{size} cannot have {fraction_digits} fraction digits"
|
37
|
+
)
|
33
38
|
self._fraction_digits = fraction_digits
|
34
39
|
self._is_signed = is_signed
|
35
40
|
|
@@ -1,16 +1,16 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Any, Mapping
|
2
2
|
|
3
|
-
from classiq.exceptions import ClassiqNotImplementedError
|
4
|
-
|
5
3
|
if TYPE_CHECKING:
|
6
4
|
from classiq.interface.model.handle_binding import HandleBinding
|
7
5
|
|
8
6
|
|
9
7
|
class QmodSizedProxy:
|
10
|
-
def __init__(self, size: int) -> None:
|
8
|
+
def __init__(self, handle: "HandleBinding", size: int) -> None:
|
9
|
+
self._handle = handle
|
11
10
|
self._size = size
|
12
11
|
|
13
|
-
|
12
|
+
@property
|
13
|
+
def size(self) -> int:
|
14
14
|
return self._size
|
15
15
|
|
16
16
|
def __str__(self) -> str:
|
@@ -22,7 +22,7 @@ class QmodSizedProxy:
|
|
22
22
|
|
23
23
|
@property
|
24
24
|
def handle(self) -> "HandleBinding":
|
25
|
-
|
25
|
+
return self._handle
|
26
26
|
|
27
27
|
@property
|
28
28
|
def len(self) -> int:
|