classiq 0.36.1__py3-none-any.whl → 0.37.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 +1 -0
- classiq/_internals/api_wrapper.py +24 -6
- classiq/_internals/authentication/device.py +6 -3
- classiq/_internals/authentication/token_manager.py +21 -5
- classiq/_internals/client.py +7 -2
- classiq/_internals/config.py +12 -0
- classiq/_internals/host_checker.py +1 -1
- classiq/_internals/jobs.py +3 -1
- classiq/_internals/type_validation.py +3 -6
- classiq/analyzer/analyzer.py +1 -0
- classiq/analyzer/rb.py +3 -5
- classiq/applications_model_constructors/chemistry_model_constructor.py +0 -1
- classiq/applications_model_constructors/grover_model_constructor.py +27 -18
- classiq/execution/jobs.py +13 -4
- classiq/executor.py +3 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +0 -6
- classiq/interface/analyzer/result.py +0 -4
- classiq/interface/backend/backend_preferences.py +2 -2
- classiq/interface/backend/quantum_backend_providers.py +1 -1
- classiq/interface/execution/resource_estimator.py +7 -0
- classiq/interface/execution/result.py +5 -0
- classiq/interface/generator/ansatz_library.py +3 -3
- classiq/interface/generator/arith/binary_ops.py +1 -3
- classiq/interface/generator/expressions/atomic_expression_functions.py +2 -0
- classiq/interface/generator/expressions/qmod_qnum_proxy.py +22 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +2 -12
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +140 -14
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +3 -20
- classiq/interface/generator/functions/native_function_definition.py +3 -3
- classiq/interface/generator/model/constraints.py +3 -3
- classiq/interface/generator/model/preferences/preferences.py +10 -8
- classiq/interface/generator/noise_properties.py +5 -5
- classiq/interface/generator/qpe.py +5 -5
- classiq/interface/generator/quantum_function_call.py +5 -3
- classiq/interface/generator/visitor.py +1 -2
- classiq/interface/hardware.py +1 -1
- classiq/interface/model/native_function_definition.py +2 -24
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +2 -2
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +2 -2
- classiq/interface/model/quantum_expressions/control_state.py +38 -0
- classiq/interface/model/quantum_expressions/quantum_expression.py +12 -9
- classiq/interface/model/quantum_function_call.py +3 -0
- classiq/interface/model/quantum_function_declaration.py +3 -3
- classiq/interface/model/quantum_if_operation.py +95 -0
- classiq/interface/model/validations/handles_validator.py +7 -15
- classiq/interface/server/routes.py +10 -6
- classiq/model/function_handler.pyi +84 -84
- classiq/model/model.py +1 -0
- classiq/qmod/__init__.py +4 -1
- classiq/qmod/builtins/__init__.py +13 -1
- classiq/qmod/builtins/classical_execution_primitives.py +109 -0
- classiq/qmod/builtins/classical_functions.py +68 -0
- classiq/qmod/builtins/functions.py +47 -21
- classiq/qmod/builtins/operations.py +15 -29
- classiq/qmod/classical_function.py +40 -0
- classiq/qmod/declaration_inferrer.py +5 -2
- classiq/qmod/qmod_variable.py +15 -3
- classiq/qmod/quantum_callable.py +24 -3
- classiq/qmod/quantum_expandable.py +99 -17
- classiq/qmod/quantum_function.py +12 -2
- classiq/qmod/symbolic.py +109 -107
- classiq/qmod/symbolic_expr.py +1 -4
- classiq/qmod/symbolic_type.py +8 -0
- classiq/quantum_functions/decorators.py +2 -4
- classiq/quantum_functions/function_library.py +1 -0
- {classiq-0.36.1.dist-info → classiq-0.37.1.dist-info}/METADATA +1 -1
- {classiq-0.36.1.dist-info → classiq-0.37.1.dist-info}/RECORD +69 -61
- classiq/interface/model/local_variable_declaration.py +0 -7
- {classiq-0.36.1.dist-info → classiq-0.37.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
from sympy import Symbol
|
2
|
+
|
3
|
+
from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
|
4
|
+
from classiq.interface.model.quantum_type import QuantumNumeric
|
5
|
+
|
6
|
+
|
7
|
+
class QmodQNumProxy(Symbol, QmodSizedProxy):
|
8
|
+
def __new__(cls, name, **assumptions):
|
9
|
+
return super().__new__(cls, name, **assumptions)
|
10
|
+
|
11
|
+
def __init__(self, name: str, quantum_type: QuantumNumeric) -> None:
|
12
|
+
super().__init__(quantum_type.size_in_bits)
|
13
|
+
self._fraction_digits = quantum_type.fraction_digits
|
14
|
+
self._is_signed = quantum_type.is_signed
|
15
|
+
|
16
|
+
@property
|
17
|
+
def fraction_digits(self) -> int:
|
18
|
+
return self._fraction_digits
|
19
|
+
|
20
|
+
@property
|
21
|
+
def is_signed(self) -> bool:
|
22
|
+
return self._is_signed
|
@@ -1,16 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class QmodSizedProxy(Symbol):
|
5
|
-
def __new__(cls, name, **assumptions):
|
6
|
-
return super().__new__(cls, name, **assumptions)
|
7
|
-
|
8
|
-
def __init__(self, name: str, size: int) -> None:
|
1
|
+
class QmodSizedProxy:
|
2
|
+
def __init__(self, size: int) -> None:
|
9
3
|
self._size = size
|
10
4
|
|
11
|
-
@property
|
12
|
-
def size(self) -> int:
|
13
|
-
return self.args[0]
|
14
|
-
|
15
5
|
def __len__(self) -> int:
|
16
6
|
return self._size
|
classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py
CHANGED
@@ -34,35 +34,101 @@ QFT = QuantumFunctionDeclaration.parse_raw(
|
|
34
34
|
}"""
|
35
35
|
)
|
36
36
|
|
37
|
-
|
37
|
+
QPE_FLEXIBLE = QuantumFunctionDeclaration.parse_raw(
|
38
38
|
"""{
|
39
|
-
"name": "
|
40
|
-
"param_decls": {
|
41
|
-
|
42
|
-
|
39
|
+
"name": "qpe_flexible",
|
40
|
+
"param_decls": {},
|
41
|
+
"port_declarations": {
|
42
|
+
"phase": {
|
43
|
+
"name": "phase",
|
44
|
+
"quantum_type": {
|
45
|
+
"size": null,
|
46
|
+
"kind": "qnum"
|
47
|
+
},
|
48
|
+
"direction": "inout"
|
43
49
|
}
|
44
50
|
},
|
51
|
+
"operand_declarations": {
|
52
|
+
"unitary_with_power": {
|
53
|
+
"name": "unitary_with_power",
|
54
|
+
"positional_arg_declarations": [
|
55
|
+
{
|
56
|
+
"name": "arg0",
|
57
|
+
"classical_type": {
|
58
|
+
"kind": "int"
|
59
|
+
}
|
60
|
+
}
|
61
|
+
],
|
62
|
+
"is_list": false
|
63
|
+
}
|
64
|
+
},
|
65
|
+
"positional_arg_declarations": [
|
66
|
+
{
|
67
|
+
"name": "unitary_with_power",
|
68
|
+
"positional_arg_declarations": [
|
69
|
+
{
|
70
|
+
"name": "arg0",
|
71
|
+
"classical_type": {
|
72
|
+
"kind": "int"
|
73
|
+
}
|
74
|
+
}
|
75
|
+
],
|
76
|
+
"is_list": false
|
77
|
+
},
|
78
|
+
{
|
79
|
+
"name": "phase",
|
80
|
+
"quantum_type": {
|
81
|
+
"size": null,
|
82
|
+
"kind": "qnum"
|
83
|
+
},
|
84
|
+
"direction": "inout"
|
85
|
+
}
|
86
|
+
]
|
87
|
+
}"""
|
88
|
+
)
|
89
|
+
|
90
|
+
QPE = QuantumFunctionDeclaration.parse_raw(
|
91
|
+
"""{
|
92
|
+
"name": "qpe",
|
93
|
+
"param_decls": {},
|
45
94
|
"port_declarations": {
|
46
95
|
"phase": {
|
47
96
|
"name": "phase",
|
48
|
-
"
|
49
|
-
"
|
97
|
+
"quantum_type": {
|
98
|
+
"size": null,
|
99
|
+
"kind": "qnum"
|
50
100
|
},
|
51
101
|
"direction": "inout"
|
52
102
|
}
|
53
103
|
},
|
54
104
|
"operand_declarations": {
|
55
105
|
"unitary": {
|
56
|
-
"name": "unitary"
|
106
|
+
"name": "unitary",
|
107
|
+
"positional_arg_declarations": [],
|
108
|
+
"is_list": false
|
57
109
|
}
|
58
110
|
},
|
59
|
-
"positional_arg_declarations": [
|
111
|
+
"positional_arg_declarations": [
|
112
|
+
{
|
113
|
+
"name": "unitary",
|
114
|
+
"positional_arg_declarations": [],
|
115
|
+
"is_list": false
|
116
|
+
},
|
117
|
+
{
|
118
|
+
"name": "phase",
|
119
|
+
"quantum_type": {
|
120
|
+
"size": null,
|
121
|
+
"kind": "qnum"
|
122
|
+
},
|
123
|
+
"direction": "inout"
|
124
|
+
}
|
125
|
+
]
|
60
126
|
}"""
|
61
127
|
)
|
62
128
|
|
63
|
-
|
129
|
+
STANDARD_QPE = QuantumFunctionDeclaration.parse_raw(
|
64
130
|
"""{
|
65
|
-
"name": "
|
131
|
+
"name": "standard_qpe",
|
66
132
|
"param_decls": {
|
67
133
|
"precision": {
|
68
134
|
"kind": "int"
|
@@ -74,7 +140,7 @@ QPE = QuantumFunctionDeclaration.parse_raw(
|
|
74
140
|
"size": {
|
75
141
|
"expr": "precision"
|
76
142
|
},
|
77
|
-
"direction": "
|
143
|
+
"direction": "inout"
|
78
144
|
}
|
79
145
|
},
|
80
146
|
"operand_declarations": {
|
@@ -450,7 +516,7 @@ PREPARE_INT = QuantumFunctionDeclaration.parse_raw(
|
|
450
516
|
"out": {
|
451
517
|
"name": "out",
|
452
518
|
"quantum_type": {
|
453
|
-
"kind": "
|
519
|
+
"kind": "qnum"
|
454
520
|
},
|
455
521
|
"direction": "output"
|
456
522
|
}
|
@@ -711,11 +777,70 @@ FULL_HEA = QuantumFunctionDeclaration.parse_raw(
|
|
711
777
|
}"""
|
712
778
|
)
|
713
779
|
|
780
|
+
SWAP_TEST = QuantumFunctionDeclaration.parse_raw(
|
781
|
+
"""{
|
782
|
+
"name": "swap_test",
|
783
|
+
"param_decls": {},
|
784
|
+
"port_declarations": {
|
785
|
+
"state1": {
|
786
|
+
"name": "state1",
|
787
|
+
"quantum_type": {
|
788
|
+
"length": null,
|
789
|
+
"kind": "qvec"
|
790
|
+
},
|
791
|
+
"direction": "inout"
|
792
|
+
},
|
793
|
+
"state2": {
|
794
|
+
"name": "state2",
|
795
|
+
"quantum_type": {
|
796
|
+
"length": null,
|
797
|
+
"kind": "qvec"
|
798
|
+
},
|
799
|
+
"direction": "inout"
|
800
|
+
},
|
801
|
+
"test": {
|
802
|
+
"name": "test",
|
803
|
+
"quantum_type": {
|
804
|
+
"kind": "qbit"
|
805
|
+
},
|
806
|
+
"direction": "output"
|
807
|
+
}
|
808
|
+
},
|
809
|
+
"operand_declarations": {},
|
810
|
+
"positional_arg_declarations": [
|
811
|
+
{
|
812
|
+
"name": "state1",
|
813
|
+
"quantum_type": {
|
814
|
+
"length": null,
|
815
|
+
"kind": "qvec"
|
816
|
+
},
|
817
|
+
"direction": "inout"
|
818
|
+
},
|
819
|
+
{
|
820
|
+
"name": "state2",
|
821
|
+
"quantum_type": {
|
822
|
+
"length": null,
|
823
|
+
"kind": "qvec"
|
824
|
+
},
|
825
|
+
"direction": "inout"
|
826
|
+
},
|
827
|
+
{
|
828
|
+
"name": "test",
|
829
|
+
"quantum_type": {
|
830
|
+
"kind": "qbit"
|
831
|
+
},
|
832
|
+
"direction": "output"
|
833
|
+
}
|
834
|
+
]
|
835
|
+
}"""
|
836
|
+
)
|
837
|
+
|
714
838
|
__all__ = [
|
715
839
|
"QFT_STEP",
|
716
840
|
"QFT",
|
717
|
-
"
|
841
|
+
"QPE_FLEXIBLE",
|
718
842
|
"QPE",
|
843
|
+
"STANDARD_QPE",
|
719
844
|
"SINGLE_PAULI",
|
720
845
|
"LINEAR_PAULI_ROTATIONS",
|
721
846
|
"AMPLITUDE_ESTIMATION",
|
@@ -733,4 +858,5 @@ __all__ = [
|
|
733
858
|
"QAOA_INIT",
|
734
859
|
"QAOA_PENALTY",
|
735
860
|
"FULL_HEA",
|
861
|
+
"SWAP_TEST",
|
736
862
|
]
|
@@ -9,7 +9,6 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
9
9
|
QuantumFunctionDeclaration,
|
10
10
|
QuantumOperandDeclaration,
|
11
11
|
)
|
12
|
-
from classiq.interface.model.quantum_type import QuantumInteger
|
13
12
|
|
14
13
|
REPEAT_OPERATOR = QuantumFunctionDeclaration(
|
15
14
|
name="repeat",
|
@@ -22,6 +21,7 @@ REPEAT_OPERATOR = QuantumFunctionDeclaration(
|
|
22
21
|
)
|
23
22
|
|
24
23
|
OPERAND_FIELD_NAME = "operand"
|
24
|
+
CTRL_FIELD_NAME = "ctrl"
|
25
25
|
|
26
26
|
|
27
27
|
INVERT_OPERATOR = QuantumFunctionDeclaration(
|
@@ -35,8 +35,8 @@ INVERT_OPERATOR = QuantumFunctionDeclaration(
|
|
35
35
|
CONTROL_OPERATOR = QuantumFunctionDeclaration(
|
36
36
|
name="control",
|
37
37
|
port_declarations={
|
38
|
-
|
39
|
-
name=
|
38
|
+
CTRL_FIELD_NAME: PortDeclaration(
|
39
|
+
name=CTRL_FIELD_NAME,
|
40
40
|
direction=PortDeclarationDirection.Inout,
|
41
41
|
)
|
42
42
|
},
|
@@ -118,22 +118,6 @@ POWER_OPERATOR = QuantumFunctionDeclaration(
|
|
118
118
|
},
|
119
119
|
)
|
120
120
|
|
121
|
-
|
122
|
-
CONTROL_WITH_VALUE_OPERATOR = QuantumFunctionDeclaration(
|
123
|
-
name="control_with_value",
|
124
|
-
param_decls={"ctrl_val": Integer()},
|
125
|
-
port_declarations={
|
126
|
-
"ctrl": PortDeclaration(
|
127
|
-
name="ctrl",
|
128
|
-
quantum_type=QuantumInteger(),
|
129
|
-
direction=PortDeclarationDirection.Inout,
|
130
|
-
)
|
131
|
-
},
|
132
|
-
operand_declarations={
|
133
|
-
OPERAND_FIELD_NAME: QuantumOperandDeclaration(name=OPERAND_FIELD_NAME)
|
134
|
-
},
|
135
|
-
)
|
136
|
-
|
137
121
|
APPLY = QuantumFunctionDeclaration(
|
138
122
|
name="apply",
|
139
123
|
operand_declarations={
|
@@ -174,7 +158,6 @@ BUILTIN_QUANTUM_OPERATOR_LIST = [
|
|
174
158
|
SPLIT_OPERATOR,
|
175
159
|
PERMUTE_OPERATOR,
|
176
160
|
POWER_OPERATOR,
|
177
|
-
CONTROL_WITH_VALUE_OPERATOR,
|
178
161
|
APPLY,
|
179
162
|
COMPUTE,
|
180
163
|
UNCOMPUTE,
|
@@ -89,9 +89,9 @@ class SynthesisNativeFunctionDefinition(SynthesisQuantumFunctionDeclaration):
|
|
89
89
|
|
90
90
|
@pydantic.root_validator
|
91
91
|
def validate_ports(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
92
|
-
port_declarations: Optional[
|
93
|
-
|
94
|
-
|
92
|
+
port_declarations: Optional[Dict[IOName, SynthesisPortDeclaration]] = (
|
93
|
+
values.get("port_declarations")
|
94
|
+
)
|
95
95
|
if port_declarations is None:
|
96
96
|
return values
|
97
97
|
cls._validate_direction_ports(
|
@@ -40,9 +40,9 @@ class Constraints(BaseModel, extra=Extra.forbid):
|
|
40
40
|
)
|
41
41
|
max_depth: Optional[pydantic.PositiveInt] = None
|
42
42
|
|
43
|
-
max_gate_count: Dict[
|
44
|
-
|
45
|
-
|
43
|
+
max_gate_count: Dict[TranspilerBasisGates, pydantic.NonNegativeInt] = (
|
44
|
+
pydantic.Field(default_factory=lambda: defaultdict(int))
|
45
|
+
)
|
46
46
|
|
47
47
|
optimization_parameter: OptimizationParameterType = pydantic.Field(
|
48
48
|
default=OptimizationParameter.NO_OPTIMIZATION,
|
@@ -78,15 +78,17 @@ class Preferences(pydantic.BaseModel, extra=pydantic.Extra.forbid):
|
|
78
78
|
default=None
|
79
79
|
)
|
80
80
|
machine_precision: PydanticMachinePrecision = MAXIMAL_MACHINE_PRECISION
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
|
82
|
+
backend_service_provider: Optional[Union[Provider, ProviderVendor, str]] = (
|
83
|
+
pydantic.Field(
|
84
|
+
default=None,
|
85
|
+
description="Provider company or cloud for the requested backend.",
|
86
|
+
)
|
85
87
|
)
|
86
|
-
backend_name: Optional[
|
87
|
-
|
88
|
-
|
89
|
-
|
88
|
+
backend_name: Optional[Union[PydanticBackendName, AllBackendsNameByVendor]] = (
|
89
|
+
pydantic.Field(
|
90
|
+
default=None, description="Name of the requested backend or target."
|
91
|
+
)
|
90
92
|
)
|
91
93
|
custom_hardware_settings: CustomHardwareSettings = pydantic.Field(
|
92
94
|
default_factory=CustomHardwareSettings,
|
@@ -7,9 +7,9 @@ from classiq.interface.helpers.custom_pydantic_types import PydanticProbabilityF
|
|
7
7
|
|
8
8
|
|
9
9
|
class NoiseProperties(BaseModel):
|
10
|
-
measurement_bit_flip_probability: Optional[
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
measurement_bit_flip_probability: Optional[PydanticProbabilityFloat] = (
|
11
|
+
pydantic.Field(
|
12
|
+
default=None,
|
13
|
+
description="Probability of measuring the wrong value for each qubit.",
|
14
|
+
)
|
15
15
|
)
|
@@ -84,11 +84,11 @@ class PhaseEstimation(FunctionParams):
|
|
84
84
|
description="The unitary function parameters.",
|
85
85
|
default_factory=CustomFunction,
|
86
86
|
)
|
87
|
-
exponentiation_specification: Optional[
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
exponentiation_specification: Optional[ExponentiationSpecification] = (
|
88
|
+
pydantic.Field(
|
89
|
+
default=None,
|
90
|
+
description="The specifications for phase estimation of exponentiation functions.",
|
91
|
+
)
|
92
92
|
)
|
93
93
|
|
94
94
|
_output_name: IOName = pydantic.PrivateAttr(
|
@@ -537,9 +537,11 @@ class SynthesisQuantumFunctionCall(BaseModel):
|
|
537
537
|
valid_matches: List[Match] = []
|
538
538
|
invalid_expressions: List[str] = []
|
539
539
|
for expression, expression_match in zip(expressions, expression_matches):
|
540
|
-
|
541
|
-
expression
|
542
|
-
|
540
|
+
(
|
541
|
+
invalid_expressions.append(expression)
|
542
|
+
if expression_match is None
|
543
|
+
else valid_matches.append(expression_match)
|
544
|
+
)
|
543
545
|
|
544
546
|
invalid_slicings: List[str] = []
|
545
547
|
invalid_names: List[str] = []
|
@@ -81,8 +81,7 @@ class Visitor:
|
|
81
81
|
class Transformer(Visitor):
|
82
82
|
if TYPE_CHECKING:
|
83
83
|
|
84
|
-
def visit(self, node: NodeType) -> Any:
|
85
|
-
...
|
84
|
+
def visit(self, node: NodeType) -> Any: ...
|
86
85
|
|
87
86
|
def visit_list(self, node: List[NodeType]) -> List[RetType]:
|
88
87
|
return [self.visit(elem) for elem in node]
|
classiq/interface/hardware.py
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import List
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
5
|
-
from classiq.interface.model.local_variable_declaration import LocalVariableDeclaration
|
6
|
-
from classiq.interface.model.port_declaration import PortDeclaration
|
7
5
|
from classiq.interface.model.quantum_function_call import ConcreteQuantumStatement
|
8
6
|
from classiq.interface.model.quantum_function_declaration import (
|
9
7
|
QuantumFunctionDeclaration,
|
@@ -28,12 +26,8 @@ class NativeFunctionDefinition(QuantumFunctionDeclaration):
|
|
28
26
|
default_factory=list, description="List of function calls to perform."
|
29
27
|
)
|
30
28
|
|
31
|
-
local_handles: List[LocalVariableDeclaration] = pydantic.Field(
|
32
|
-
default_factory=list, description="List of local handles."
|
33
|
-
)
|
34
|
-
|
35
29
|
def validate_body(self) -> None:
|
36
|
-
handle_validator = HandleValidator(self.port_declarations
|
30
|
+
handle_validator = HandleValidator(self.port_declarations)
|
37
31
|
|
38
32
|
for statement in self.body:
|
39
33
|
if isinstance(statement, VariableDeclarationStatement):
|
@@ -42,19 +36,3 @@ class NativeFunctionDefinition(QuantumFunctionDeclaration):
|
|
42
36
|
handle_validator.handle_call(statement)
|
43
37
|
|
44
38
|
handle_validator.report_errored_handles(ClassiqValueError)
|
45
|
-
|
46
|
-
@pydantic.validator("local_handles")
|
47
|
-
def validate_local_handles(
|
48
|
-
cls, local_handles: List[LocalVariableDeclaration], values: Dict[str, Any]
|
49
|
-
) -> List[LocalVariableDeclaration]:
|
50
|
-
ports: Optional[Dict[str, PortDeclaration]] = values.get("port_declarations")
|
51
|
-
if ports is None:
|
52
|
-
return local_handles
|
53
|
-
|
54
|
-
intersection = {handle.name for handle in local_handles} & ports.keys()
|
55
|
-
if intersection:
|
56
|
-
raise ClassiqValueError(
|
57
|
-
f"The names {intersection} are both local handles and ports"
|
58
|
-
)
|
59
|
-
|
60
|
-
return local_handles
|
@@ -12,7 +12,7 @@ from classiq.interface.model.handle_binding import (
|
|
12
12
|
SubscriptHandleBinding,
|
13
13
|
)
|
14
14
|
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
15
|
-
|
15
|
+
QuantumAssignmentOperation,
|
16
16
|
)
|
17
17
|
from classiq.interface.model.quantum_type import QuantumBit, QuantumNumeric, QuantumType
|
18
18
|
|
@@ -27,7 +27,7 @@ VAR_DOMAIN_ILLEGAL = (
|
|
27
27
|
)
|
28
28
|
|
29
29
|
|
30
|
-
class AmplitudeLoadingOperation(
|
30
|
+
class AmplitudeLoadingOperation(QuantumAssignmentOperation):
|
31
31
|
_result_type: QuantumType = pydantic.PrivateAttr(default_factory=QuantumBit)
|
32
32
|
|
33
33
|
@property
|
@@ -12,12 +12,12 @@ from classiq.interface.model.handle_binding import (
|
|
12
12
|
SubscriptHandleBinding,
|
13
13
|
)
|
14
14
|
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
15
|
-
|
15
|
+
QuantumAssignmentOperation,
|
16
16
|
)
|
17
17
|
from classiq.interface.model.quantum_type import QuantumType
|
18
18
|
|
19
19
|
|
20
|
-
class ArithmeticOperation(
|
20
|
+
class ArithmeticOperation(QuantumAssignmentOperation):
|
21
21
|
inplace_result: bool = pydantic.Field(
|
22
22
|
description="Determines whether the result variable is initialized",
|
23
23
|
)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
from classiq.exceptions import ClassiqValueError
|
2
|
+
|
3
|
+
|
4
|
+
def min_unsigned_bit_length(number: int) -> int:
|
5
|
+
if number < 0:
|
6
|
+
raise ClassiqValueError(
|
7
|
+
f"Quantum register is not signed but control value " # noqa: B907
|
8
|
+
f"'{number}' is negative"
|
9
|
+
)
|
10
|
+
return 1 if number == 0 else number.bit_length()
|
11
|
+
|
12
|
+
|
13
|
+
def min_signed_bit_length(number: int) -> int:
|
14
|
+
pos_val = abs(number)
|
15
|
+
is_whole = pos_val & (pos_val - 1) == 0
|
16
|
+
if number <= 0 and is_whole:
|
17
|
+
return min_unsigned_bit_length(pos_val)
|
18
|
+
return min_unsigned_bit_length(pos_val) + 1
|
19
|
+
|
20
|
+
|
21
|
+
def min_bit_length(number: int, is_signed: bool) -> int:
|
22
|
+
return (
|
23
|
+
min_signed_bit_length(number) if is_signed else min_unsigned_bit_length(number)
|
24
|
+
)
|
25
|
+
|
26
|
+
|
27
|
+
def to_twos_complement(value: int, bits: int, is_signed: bool) -> str:
|
28
|
+
required_bits = min_bit_length(value, is_signed)
|
29
|
+
if bits < required_bits:
|
30
|
+
raise ClassiqValueError(
|
31
|
+
f"Cannot express '{value}' using {bits} bits: " # noqa: B907
|
32
|
+
f"at least {required_bits} bits are required"
|
33
|
+
)
|
34
|
+
if value >= 0:
|
35
|
+
return bin(value)[2:].zfill(bits)[::-1]
|
36
|
+
mask = (1 << bits) - 1
|
37
|
+
value = (abs(value) ^ mask) + 1
|
38
|
+
return bin(value)[:1:-1].rjust(bits, "1")
|
@@ -35,18 +35,12 @@ class VarRefCollector(ast.NodeVisitor):
|
|
35
35
|
|
36
36
|
class QuantumExpressionOperation(QuantumOperation):
|
37
37
|
expression: Expression = pydantic.Field()
|
38
|
-
result_var: HandleBinding = pydantic.Field(
|
39
|
-
description="The variable storing the expression result"
|
40
|
-
)
|
41
38
|
_var_handles: List[HandleBinding] = pydantic.PrivateAttr(
|
42
39
|
default_factory=list,
|
43
40
|
)
|
44
41
|
_var_types: Dict[str, QuantumType] = pydantic.PrivateAttr(
|
45
42
|
default_factory=dict,
|
46
43
|
)
|
47
|
-
_result_type: Optional[QuantumType] = pydantic.PrivateAttr(
|
48
|
-
default=None,
|
49
|
-
)
|
50
44
|
|
51
45
|
@property
|
52
46
|
def var_handles(self) -> List[HandleBinding]:
|
@@ -75,15 +69,24 @@ class QuantumExpressionOperation(QuantumOperation):
|
|
75
69
|
]:
|
76
70
|
return nameables_to_dict(self.var_handles)
|
77
71
|
|
78
|
-
|
79
|
-
|
80
|
-
|
72
|
+
|
73
|
+
class QuantumAssignmentOperation(QuantumExpressionOperation):
|
74
|
+
result_var: HandleBinding = pydantic.Field(
|
75
|
+
description="The variable storing the expression result"
|
76
|
+
)
|
77
|
+
_result_type: Optional[QuantumType] = pydantic.PrivateAttr(
|
78
|
+
default=None,
|
79
|
+
)
|
81
80
|
|
82
81
|
@property
|
83
82
|
def result_type(self) -> QuantumType:
|
84
83
|
assert self._result_type is not None
|
85
84
|
return self._result_type
|
86
85
|
|
86
|
+
@property
|
87
|
+
def wiring_outputs(self) -> Mapping[str, HandleBinding]:
|
88
|
+
return {self.result_name(): self.result_var}
|
89
|
+
|
87
90
|
@classmethod
|
88
91
|
@abc.abstractmethod
|
89
92
|
def result_name(cls) -> str:
|
@@ -38,6 +38,7 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
38
38
|
QuantumFunctionDeclaration,
|
39
39
|
QuantumOperandDeclaration,
|
40
40
|
)
|
41
|
+
from classiq.interface.model.quantum_if_operation import QuantumIfOperation
|
41
42
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
42
43
|
from classiq.interface.model.validation_handle import get_unique_handle_names
|
43
44
|
from classiq.interface.model.variable_declaration_statement import (
|
@@ -356,6 +357,7 @@ ConcreteQuantumStatement = Union[
|
|
356
357
|
BindOperation,
|
357
358
|
NumericReinterpretationOperation,
|
358
359
|
InplaceBinaryOperation,
|
360
|
+
QuantumIfOperation,
|
359
361
|
]
|
360
362
|
|
361
363
|
|
@@ -405,6 +407,7 @@ QuantumCallable = Union[str, QuantumLambdaFunction]
|
|
405
407
|
QuantumOperand = Union[QuantumCallable, List[QuantumCallable], LambdaListComprehension]
|
406
408
|
|
407
409
|
QuantumFunctionCall.update_forward_refs()
|
410
|
+
QuantumIfOperation.update_forward_refs(QuantumOperand=QuantumOperand)
|
408
411
|
|
409
412
|
|
410
413
|
def get_lambda_defs(operand: QuantumOperand) -> List[QuantumCallable]:
|
@@ -83,9 +83,9 @@ class QuantumFunctionDeclaration(FunctionDeclaration):
|
|
83
83
|
default_factory=list
|
84
84
|
)
|
85
85
|
|
86
|
-
BUILTIN_FUNCTION_DECLARATIONS: ClassVar[
|
87
|
-
|
88
|
-
|
86
|
+
BUILTIN_FUNCTION_DECLARATIONS: ClassVar[Dict[str, "QuantumFunctionDeclaration"]] = (
|
87
|
+
{}
|
88
|
+
)
|
89
89
|
|
90
90
|
@property
|
91
91
|
def input_set(self) -> Set[str]:
|