classiq 0.39.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 +1 -0
- classiq/applications/chemistry/chemistry_model_constructor.py +1 -1
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +5 -6
- classiq/applications/combinatorial_helpers/optimization_model.py +7 -6
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -10
- classiq/applications/combinatorial_optimization/__init__.py +2 -0
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +5 -5
- classiq/interface/backend/quantum_backend_providers.py +7 -7
- classiq/interface/executor/execution_preferences.py +4 -9
- 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/expressions/qmod_qarray_proxy.py +82 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +21 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +22 -0
- 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/open_lib_functions.py +624 -76
- classiq/interface/generator/functions/classical_type.py +29 -17
- classiq/interface/generator/model/preferences/preferences.py +4 -2
- classiq/interface/model/control.py +104 -8
- classiq/interface/model/quantum_type.py +6 -5
- classiq/interface/model/resolvers/function_call_resolver.py +0 -5
- classiq/interface/model/statement_block.py +1 -4
- classiq/qmod/__init__.py +6 -2
- classiq/qmod/builtins/classical_functions.py +30 -35
- classiq/qmod/builtins/functions.py +213 -153
- classiq/qmod/builtins/operations.py +78 -24
- 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 +7 -14
- classiq/qmod/qmod_constant.py +7 -7
- classiq/qmod/qmod_parameter.py +54 -33
- classiq/qmod/qmod_struct.py +2 -2
- classiq/qmod/qmod_variable.py +40 -29
- classiq/qmod/quantum_callable.py +7 -4
- classiq/qmod/quantum_expandable.py +19 -13
- classiq/qmod/quantum_function.py +25 -2
- classiq/qmod/symbolic.py +78 -68
- classiq/qmod/symbolic_expr.py +1 -1
- classiq/qmod/symbolic_type.py +1 -4
- classiq/qmod/utilities.py +29 -0
- {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/METADATA +1 -1
- {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/RECORD +48 -50
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
- classiq/interface/model/quantum_if_operation.py +0 -94
- {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/WHEEL +0 -0
@@ -1,6 +1,8 @@
|
|
1
1
|
import inspect
|
2
|
+
import sys
|
3
|
+
import warnings
|
2
4
|
from types import FrameType
|
3
|
-
from typing import Any, Callable, Final, List, Mapping, Union
|
5
|
+
from typing import Any, Callable, Final, List, Mapping, Union, overload
|
4
6
|
|
5
7
|
from classiq.interface.generator.expressions.expression import Expression
|
6
8
|
from classiq.interface.generator.functions.builtins.internal_operators import (
|
@@ -19,7 +21,6 @@ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
19
21
|
from classiq.interface.model.quantum_function_declaration import (
|
20
22
|
QuantumOperandDeclaration,
|
21
23
|
)
|
22
|
-
from classiq.interface.model.quantum_if_operation import QuantumIf
|
23
24
|
from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
|
24
25
|
from classiq.interface.model.repeat import Repeat
|
25
26
|
from classiq.interface.model.statement_block import StatementBlock
|
@@ -30,6 +31,7 @@ from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QVar
|
|
30
31
|
from classiq.qmod.quantum_callable import QCallable
|
31
32
|
from classiq.qmod.quantum_expandable import prepare_arg
|
32
33
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
34
|
+
from classiq.qmod.utilities import get_source_ref
|
33
35
|
|
34
36
|
_MISSING_VALUE: Final[int] = -1
|
35
37
|
|
@@ -39,6 +41,7 @@ def bind(
|
|
39
41
|
destination: Union[Output[QVar], List[Output[QVar]]],
|
40
42
|
) -> None:
|
41
43
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
44
|
+
source_ref = get_source_ref(sys._getframe(1))
|
42
45
|
if not isinstance(source, list):
|
43
46
|
source = [source]
|
44
47
|
if not isinstance(destination, list):
|
@@ -47,19 +50,7 @@ def bind(
|
|
47
50
|
BindOperation(
|
48
51
|
in_handles=[src_var.get_handle_binding() for src_var in source],
|
49
52
|
out_handles=[dst_var.get_handle_binding() for dst_var in destination],
|
50
|
-
|
51
|
-
)
|
52
|
-
|
53
|
-
|
54
|
-
def control(
|
55
|
-
operand: Union[QCallable, Callable[[], None]], ctrl: Union[QBit, QArray[QBit]]
|
56
|
-
) -> None:
|
57
|
-
_validate_operand(operand)
|
58
|
-
assert QCallable.CURRENT_EXPANDABLE is not None
|
59
|
-
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
60
|
-
Control(
|
61
|
-
control=ctrl.get_handle_binding(),
|
62
|
-
body=_operand_to_body(operand),
|
53
|
+
source_ref=source_ref,
|
63
54
|
)
|
64
55
|
)
|
65
56
|
|
@@ -73,38 +64,90 @@ def if_(
|
|
73
64
|
if else_ != _MISSING_VALUE:
|
74
65
|
_validate_operand(else_)
|
75
66
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
67
|
+
source_ref = get_source_ref(sys._getframe(1))
|
76
68
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
77
69
|
ClassicalIf(
|
78
70
|
condition=Expression(expr=str(condition)),
|
79
71
|
then=_operand_to_body(then),
|
80
72
|
else_=_operand_to_body(else_) if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
|
73
|
+
source_ref=source_ref,
|
81
74
|
)
|
82
75
|
)
|
83
76
|
|
84
77
|
|
85
|
-
|
86
|
-
|
78
|
+
@overload
|
79
|
+
def control(
|
80
|
+
ctrl: Union[QBit, QArray[QBit]], operand: Union[QCallable, Callable[[], None]]
|
87
81
|
) -> None:
|
88
|
-
|
82
|
+
pass
|
83
|
+
|
84
|
+
|
85
|
+
@overload
|
86
|
+
def control(ctrl: SymbolicExpr, operand: Union[QCallable, Callable[[], None]]) -> None:
|
87
|
+
pass
|
88
|
+
|
89
|
+
|
90
|
+
def control(
|
91
|
+
ctrl: Union[SymbolicExpr, QBit, QArray[QBit]],
|
92
|
+
operand: Union[QCallable, Callable[[], None]],
|
93
|
+
) -> None:
|
94
|
+
if isinstance(operand, (SymbolicExpr, QVar)) and isinstance(
|
95
|
+
control, (QCallable, Callable)
|
96
|
+
): # type:ignore[unreachable]
|
97
|
+
warnings.warn( # type:ignore[unreachable]
|
98
|
+
"The `control` syntax has changed. Switch the `ctrl` and "
|
99
|
+
"`operand` arguments. The old syntax will not be supported in the future.",
|
100
|
+
category=DeprecationWarning,
|
101
|
+
stacklevel=2,
|
102
|
+
)
|
103
|
+
ctrl, operand = operand, ctrl
|
104
|
+
if isinstance(ctrl, QNum):
|
105
|
+
warnings.warn(
|
106
|
+
"The `control` semantics has changed. Applying `control` to "
|
107
|
+
"a `QNum` without comparing it to an integer will not be supported in the "
|
108
|
+
"future.\nTips:\n 1. Use a `bind` statement to cast `ctrl` into a "
|
109
|
+
"QArray.\n 2.`control(n, ...)` is equivalent to "
|
110
|
+
"`ctrl(n == 2 ** n.size - 1, ...)` if n>=0 or to `ctrl(n == -1, ...)` if "
|
111
|
+
"n<0.",
|
112
|
+
category=DeprecationWarning,
|
113
|
+
stacklevel=2,
|
114
|
+
)
|
115
|
+
_validate_operand(operand)
|
89
116
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
117
|
+
source_ref = get_source_ref(sys._getframe(1))
|
90
118
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
91
|
-
|
92
|
-
expression=Expression(expr=str(
|
93
|
-
|
119
|
+
Control(
|
120
|
+
expression=Expression(expr=str(ctrl)),
|
121
|
+
body=_operand_to_body(operand),
|
122
|
+
source_ref=source_ref,
|
94
123
|
)
|
95
124
|
)
|
96
125
|
|
97
126
|
|
127
|
+
def quantum_if(
|
128
|
+
ctrl: SymbolicExpr, operand: Union[QCallable, Callable[[], None]]
|
129
|
+
) -> None:
|
130
|
+
warnings.warn(
|
131
|
+
"`quantum_if` is no longer supported, use `control` instead (with the "
|
132
|
+
"same arguments). `quantum_if` will be removed in a future release.",
|
133
|
+
category=DeprecationWarning,
|
134
|
+
stacklevel=2,
|
135
|
+
)
|
136
|
+
control(ctrl, operand)
|
137
|
+
|
138
|
+
|
98
139
|
def inplace_add(
|
99
140
|
value: QNum,
|
100
141
|
target: QNum,
|
101
142
|
) -> None:
|
102
143
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
144
|
+
source_ref = get_source_ref(sys._getframe(1))
|
103
145
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
104
146
|
InplaceBinaryOperation(
|
105
147
|
target=target.get_handle_binding(),
|
106
148
|
value=value.get_handle_binding(),
|
107
149
|
operation=BinaryOperation.Addition,
|
150
|
+
source_ref=source_ref,
|
108
151
|
)
|
109
152
|
)
|
110
153
|
|
@@ -114,11 +157,13 @@ def inplace_xor(
|
|
114
157
|
target: QNum,
|
115
158
|
) -> None:
|
116
159
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
160
|
+
source_ref = get_source_ref(sys._getframe(1))
|
117
161
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
118
162
|
InplaceBinaryOperation(
|
119
163
|
target=target.get_handle_binding(),
|
120
164
|
value=value.get_handle_binding(),
|
121
165
|
operation=BinaryOperation.Xor,
|
166
|
+
source_ref=source_ref,
|
122
167
|
)
|
123
168
|
)
|
124
169
|
|
@@ -130,10 +175,12 @@ def within_apply(
|
|
130
175
|
_validate_operand(compute)
|
131
176
|
_validate_operand(action)
|
132
177
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
178
|
+
source_ref = get_source_ref(sys._getframe(1))
|
133
179
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
134
180
|
WithinApply(
|
135
181
|
compute=_operand_to_body(compute),
|
136
182
|
action=_operand_to_body(action),
|
183
|
+
source_ref=source_ref,
|
137
184
|
)
|
138
185
|
)
|
139
186
|
|
@@ -141,6 +188,7 @@ def within_apply(
|
|
141
188
|
def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) -> None:
|
142
189
|
_validate_operand(iteration)
|
143
190
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
191
|
+
source_ref = get_source_ref(sys._getframe(1))
|
144
192
|
iteration_operand = prepare_arg(
|
145
193
|
REPEAT_OPERATOR.operand_declarations["iteration"], iteration
|
146
194
|
)
|
@@ -149,6 +197,7 @@ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) ->
|
|
149
197
|
iter_var=inspect.getfullargspec(iteration).args[0],
|
150
198
|
count=Expression(expr=str(count)),
|
151
199
|
body=iteration_operand.body,
|
200
|
+
source_ref=source_ref,
|
152
201
|
)
|
153
202
|
)
|
154
203
|
|
@@ -159,8 +208,13 @@ def power(
|
|
159
208
|
) -> None:
|
160
209
|
_validate_operand(operand)
|
161
210
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
211
|
+
source_ref = get_source_ref(sys._getframe(1))
|
162
212
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
163
|
-
Power(
|
213
|
+
Power(
|
214
|
+
power=Expression(expr=str(power)),
|
215
|
+
body=_operand_to_body(operand),
|
216
|
+
source_ref=source_ref,
|
217
|
+
)
|
164
218
|
)
|
165
219
|
|
166
220
|
|
@@ -169,8 +223,9 @@ def invert(
|
|
169
223
|
) -> None:
|
170
224
|
_validate_operand(operand)
|
171
225
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
226
|
+
source_ref = get_source_ref(sys._getframe(1))
|
172
227
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
173
|
-
Invert(body=_operand_to_body(operand))
|
228
|
+
Invert(body=_operand_to_body(operand), source_ref=source_ref)
|
174
229
|
)
|
175
230
|
|
176
231
|
|
@@ -240,7 +295,6 @@ __all__ = [
|
|
240
295
|
"control",
|
241
296
|
"invert",
|
242
297
|
"if_",
|
243
|
-
"quantum_if",
|
244
298
|
"inplace_add",
|
245
299
|
"inplace_xor",
|
246
300
|
"power",
|
classiq/qmod/builtins/structs.py
CHANGED
@@ -1,113 +1,115 @@
|
|
1
1
|
# This file was generated automatically - do not edit manually
|
2
2
|
|
3
|
-
from
|
3
|
+
from classiq.interface.generator.expressions.enums.ladder_operator import LadderOperator
|
4
|
+
from classiq.interface.generator.expressions.enums.pauli import Pauli
|
4
5
|
|
6
|
+
from classiq.qmod.qmod_parameter import CArray, CBool, CInt, CReal
|
5
7
|
from classiq.qmod.qmod_struct import struct
|
6
8
|
|
7
9
|
|
8
10
|
@struct
|
9
11
|
class PauliTerm:
|
10
|
-
pauli:
|
11
|
-
coefficient:
|
12
|
+
pauli: CArray[Pauli]
|
13
|
+
coefficient: CReal
|
12
14
|
|
13
15
|
|
14
16
|
@struct
|
15
17
|
class MoleculeProblem:
|
16
|
-
mapping:
|
17
|
-
z2_symmetries:
|
18
|
+
mapping: CInt
|
19
|
+
z2_symmetries: CBool
|
18
20
|
molecule: "Molecule"
|
19
|
-
freeze_core:
|
20
|
-
remove_orbitals:
|
21
|
+
freeze_core: CBool
|
22
|
+
remove_orbitals: CArray[CInt]
|
21
23
|
|
22
24
|
|
23
25
|
@struct
|
24
26
|
class Molecule:
|
25
|
-
atoms:
|
26
|
-
spin:
|
27
|
-
charge:
|
27
|
+
atoms: CArray["ChemistryAtom"]
|
28
|
+
spin: CInt
|
29
|
+
charge: CInt
|
28
30
|
|
29
31
|
|
30
32
|
@struct
|
31
33
|
class ChemistryAtom:
|
32
|
-
element:
|
34
|
+
element: CInt
|
33
35
|
position: "Position"
|
34
36
|
|
35
37
|
|
36
38
|
@struct
|
37
39
|
class Position:
|
38
|
-
x:
|
39
|
-
y:
|
40
|
-
z:
|
40
|
+
x: CReal
|
41
|
+
y: CReal
|
42
|
+
z: CReal
|
41
43
|
|
42
44
|
|
43
45
|
@struct
|
44
46
|
class FockHamiltonianProblem:
|
45
|
-
mapping:
|
46
|
-
z2_symmetries:
|
47
|
-
terms:
|
48
|
-
num_particles:
|
47
|
+
mapping: CInt
|
48
|
+
z2_symmetries: CBool
|
49
|
+
terms: CArray["LadderTerm"]
|
50
|
+
num_particles: CArray[CInt]
|
49
51
|
|
50
52
|
|
51
53
|
@struct
|
52
54
|
class LadderTerm:
|
53
|
-
coefficient:
|
54
|
-
ops:
|
55
|
+
coefficient: CReal
|
56
|
+
ops: CArray["LadderOp"]
|
55
57
|
|
56
58
|
|
57
59
|
@struct
|
58
60
|
class LadderOp:
|
59
|
-
op:
|
60
|
-
index:
|
61
|
+
op: LadderOperator
|
62
|
+
index: CInt
|
61
63
|
|
62
64
|
|
63
65
|
@struct
|
64
66
|
class CombinatorialOptimizationSolution:
|
65
|
-
probability:
|
66
|
-
cost:
|
67
|
-
solution:
|
68
|
-
count:
|
67
|
+
probability: CReal
|
68
|
+
cost: CReal
|
69
|
+
solution: CArray[CInt]
|
70
|
+
count: CInt
|
69
71
|
|
70
72
|
|
71
73
|
@struct
|
72
74
|
class GaussianModel:
|
73
|
-
num_qubits:
|
74
|
-
normal_max_value:
|
75
|
-
default_probabilities:
|
76
|
-
rhos:
|
77
|
-
loss:
|
78
|
-
min_loss:
|
75
|
+
num_qubits: CInt
|
76
|
+
normal_max_value: CReal
|
77
|
+
default_probabilities: CArray[CReal]
|
78
|
+
rhos: CArray[CReal]
|
79
|
+
loss: CArray[CInt]
|
80
|
+
min_loss: CInt
|
79
81
|
|
80
82
|
|
81
83
|
@struct
|
82
84
|
class LogNormalModel:
|
83
|
-
num_qubits:
|
84
|
-
mu:
|
85
|
-
sigma:
|
85
|
+
num_qubits: CInt
|
86
|
+
mu: CReal
|
87
|
+
sigma: CReal
|
86
88
|
|
87
89
|
|
88
90
|
@struct
|
89
91
|
class FinanceFunction:
|
90
|
-
f:
|
91
|
-
threshold:
|
92
|
-
larger:
|
93
|
-
polynomial_degree:
|
94
|
-
use_chebyshev_polynomial_approximation:
|
95
|
-
tail_probability:
|
92
|
+
f: CInt
|
93
|
+
threshold: CReal
|
94
|
+
larger: CBool
|
95
|
+
polynomial_degree: CInt
|
96
|
+
use_chebyshev_polynomial_approximation: CBool
|
97
|
+
tail_probability: CReal
|
96
98
|
|
97
99
|
|
98
100
|
@struct
|
99
101
|
class QsvmResult:
|
100
|
-
test_score:
|
101
|
-
predicted_labels:
|
102
|
+
test_score: CReal
|
103
|
+
predicted_labels: CArray[CReal]
|
102
104
|
|
103
105
|
|
104
106
|
@struct
|
105
107
|
class QSVMFeatureMapPauli:
|
106
|
-
feature_dimension:
|
107
|
-
reps:
|
108
|
-
entanglement:
|
109
|
-
alpha:
|
110
|
-
paulis:
|
108
|
+
feature_dimension: CInt
|
109
|
+
reps: CInt
|
110
|
+
entanglement: CInt
|
111
|
+
alpha: CReal
|
112
|
+
paulis: CArray[CArray[Pauli]]
|
111
113
|
|
112
114
|
|
113
115
|
__all__ = [
|
@@ -9,8 +9,8 @@ from classiq.interface.generator.functions.classical_type import (
|
|
9
9
|
ClassicalArray,
|
10
10
|
ClassicalList,
|
11
11
|
ConcreteClassicalType,
|
12
|
+
CStructBase,
|
12
13
|
Integer,
|
13
|
-
QStructBase,
|
14
14
|
Real,
|
15
15
|
Struct,
|
16
16
|
)
|
@@ -27,7 +27,7 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
27
27
|
from classiq import StructDeclaration
|
28
28
|
from classiq.exceptions import ClassiqValueError
|
29
29
|
from classiq.qmod.model_state_container import ModelStateContainer
|
30
|
-
from classiq.qmod.qmod_parameter import
|
30
|
+
from classiq.qmod.qmod_parameter import CArray, CBool, CInt, CParam, CReal, QParam
|
31
31
|
from classiq.qmod.qmod_variable import QVar, get_type_hint_expr
|
32
32
|
from classiq.qmod.quantum_callable import QCallable, QCallableList
|
33
33
|
from classiq.qmod.utilities import unmangle_keyword, version_portable_get_args
|
@@ -38,34 +38,39 @@ OPERAND_ARG_NAME = "arg{i}"
|
|
38
38
|
def python_type_to_qmod(
|
39
39
|
py_type: type, *, qmodule: ModelStateContainer
|
40
40
|
) -> Optional[ConcreteClassicalType]:
|
41
|
-
if py_type == int:
|
41
|
+
if py_type == int or py_type is CInt:
|
42
42
|
return Integer()
|
43
|
-
elif py_type == float:
|
43
|
+
elif py_type == float or py_type is CReal:
|
44
44
|
return Real()
|
45
|
-
elif py_type == bool:
|
45
|
+
elif py_type == bool or py_type is CBool:
|
46
46
|
return Bool()
|
47
47
|
elif get_origin(py_type) == list:
|
48
48
|
return ClassicalList(
|
49
49
|
element_type=python_type_to_qmod(get_args(py_type)[0], qmodule=qmodule)
|
50
50
|
)
|
51
|
-
elif get_origin(py_type) ==
|
51
|
+
elif get_origin(py_type) == CArray:
|
52
52
|
array_args = version_portable_get_args(py_type)
|
53
|
-
if len(array_args)
|
54
|
-
|
55
|
-
|
53
|
+
if len(array_args) == 1:
|
54
|
+
return ClassicalList(
|
55
|
+
element_type=python_type_to_qmod(array_args[0], qmodule=qmodule)
|
56
56
|
)
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
elif len(array_args) == 2:
|
58
|
+
return ClassicalArray(
|
59
|
+
element_type=python_type_to_qmod(array_args[0], qmodule=qmodule),
|
60
|
+
size=get_type_hint_expr(array_args[1]),
|
61
|
+
)
|
62
|
+
raise ClassiqValueError(
|
63
|
+
"CArray accepts one or two generic parameters in the form "
|
64
|
+
"`CArray[<element-type>]` or `CArray[<element-type>, <size>]`"
|
60
65
|
)
|
61
|
-
elif inspect.isclass(py_type) and issubclass(py_type,
|
66
|
+
elif inspect.isclass(py_type) and issubclass(py_type, CStructBase):
|
62
67
|
_add_qmod_struct(py_type, qmodule=qmodule)
|
63
68
|
return Struct(name=py_type.__name__)
|
64
69
|
return None
|
65
70
|
|
66
71
|
|
67
72
|
def _add_qmod_struct(
|
68
|
-
py_type: Type[
|
73
|
+
py_type: Type[CStructBase], *, qmodule: ModelStateContainer
|
69
74
|
) -> None:
|
70
75
|
if (
|
71
76
|
py_type.__name__ in StructDeclaration.BUILTIN_STRUCT_DECLARATIONS
|
@@ -85,9 +90,10 @@ def _add_qmod_struct(
|
|
85
90
|
def _extract_param_decl(
|
86
91
|
name: str, py_type: Any, *, qmodule: ModelStateContainer
|
87
92
|
) -> ClassicalParameterDeclaration:
|
88
|
-
if
|
89
|
-
|
90
|
-
|
93
|
+
if get_origin(py_type) is QParam:
|
94
|
+
if len(get_args(py_type)) != 1:
|
95
|
+
raise ClassiqValueError("QParam takes exactly one generic argument")
|
96
|
+
py_type = get_args(py_type)[0]
|
91
97
|
return ClassicalParameterDeclaration(
|
92
98
|
name=name, classical_type=python_type_to_qmod(py_type, qmodule=qmodule)
|
93
99
|
)
|
@@ -128,7 +134,13 @@ def _extract_positional_args(
|
|
128
134
|
if name == "return":
|
129
135
|
continue
|
130
136
|
name = unmangle_keyword(name)
|
131
|
-
if
|
137
|
+
if (
|
138
|
+
inspect.isclass(py_type)
|
139
|
+
and issubclass(py_type, CParam)
|
140
|
+
or inspect.isclass(py_type)
|
141
|
+
and issubclass(py_type, CStructBase)
|
142
|
+
or get_origin(py_type) in (QParam, CArray)
|
143
|
+
):
|
132
144
|
result.append(_extract_param_decl(name, py_type, qmodule=qmodule))
|
133
145
|
elif QVar.from_type_hint(py_type) is not None:
|
134
146
|
result.append(_extract_port_decl(name, py_type))
|
@@ -5,6 +5,8 @@ from typing import Callable, Dict, List, Mapping, Type
|
|
5
5
|
|
6
6
|
import numpy as np
|
7
7
|
|
8
|
+
from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
|
9
|
+
|
8
10
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
9
11
|
|
10
12
|
IDENTIFIER = re.compile(r"[a-zA-Z_]\w*")
|
@@ -57,11 +59,10 @@ class ASTToQMODCode:
|
|
57
59
|
return self.indent.join(self.ast_to_code(child) for child in node.body)
|
58
60
|
elif isinstance(node, ast.Attribute):
|
59
61
|
# Enum attribute access
|
60
|
-
if not isinstance(node.
|
61
|
-
raise AssertionError("Error parsing enum attribute access")
|
62
|
-
if not (IDENTIFIER.match(node.value.id) and IDENTIFIER.match(node.attr)):
|
62
|
+
if not isinstance(node.attr, str):
|
63
63
|
raise AssertionError("Error parsing enum attribute access")
|
64
|
-
|
64
|
+
access_operator = "." if node.attr in CLASSICAL_ATTRIBUTES else "::"
|
65
|
+
return f"{self.ast_to_code(node.value)!s}{access_operator}{node.attr!s}"
|
65
66
|
elif isinstance(node, ast.Name):
|
66
67
|
return node.id
|
67
68
|
elif isinstance(node, ast.Num):
|
@@ -41,7 +41,6 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
41
41
|
QuantumFunctionDeclaration,
|
42
42
|
QuantumOperandDeclaration,
|
43
43
|
)
|
44
|
-
from classiq.interface.model.quantum_if_operation import QuantumIf
|
45
44
|
from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
|
46
45
|
from classiq.interface.model.quantum_type import (
|
47
46
|
QuantumBit,
|
@@ -213,17 +212,11 @@ class DSLPrettyPrinter(Visitor):
|
|
213
212
|
)
|
214
213
|
return f"{self._indent}{func_call.func_name}{f'[{self.visit(func_call.function.index)}]' if isinstance(func_call.function, OperandIdentifier) else ''}{gen_time_arg_list}({quantum_args});\n"
|
215
214
|
|
216
|
-
def visit_Control(self,
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
return
|
221
|
-
|
222
|
-
def visit_QuantumIf(self, op: QuantumIf) -> str:
|
223
|
-
quantum_if = f"{self._indent}quantum_if ({self.visit(op.expression)}) {{\n"
|
224
|
-
quantum_if += self._visit_body(op.then)
|
225
|
-
quantum_if += f"{self._indent}}}\n"
|
226
|
-
return quantum_if
|
215
|
+
def visit_Control(self, op: Control) -> str:
|
216
|
+
control = f"{self._indent}control ({self.visit(op.expression)}) {{\n"
|
217
|
+
control += self._visit_body(op.body)
|
218
|
+
control += f"{self._indent}}}\n"
|
219
|
+
return control
|
227
220
|
|
228
221
|
def visit_ClassicalIf(self, op: ClassicalIf) -> str:
|
229
222
|
classical_if = f"{self._indent}if ({self.visit(op.condition)}) {{\n"
|
@@ -309,10 +302,10 @@ class DSLPrettyPrinter(Visitor):
|
|
309
302
|
return var_ref.name
|
310
303
|
|
311
304
|
def visit_SlicedHandleBinding(self, var_ref: SlicedHandleBinding) -> str:
|
312
|
-
return
|
305
|
+
return f"{var_ref.name}[{self.visit(var_ref.start)}:{self.visit(var_ref.end)}]"
|
313
306
|
|
314
307
|
def visit_SubscriptHandleBinding(self, var_ref: SubscriptHandleBinding) -> str:
|
315
|
-
return
|
308
|
+
return f"{var_ref.name}[{self.visit(var_ref.index)}]"
|
316
309
|
|
317
310
|
def visit_ArithmeticOperation(self, arith_op: ArithmeticOperation) -> str:
|
318
311
|
op = "^=" if arith_op.inplace_result else "="
|
classiq/qmod/qmod_constant.py
CHANGED
@@ -6,13 +6,13 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
6
6
|
from classiq.interface.generator.functions.classical_type import (
|
7
7
|
ClassicalArray,
|
8
8
|
ClassicalList,
|
9
|
-
|
9
|
+
CStructBase,
|
10
10
|
)
|
11
11
|
|
12
12
|
from classiq.exceptions import ClassiqError
|
13
13
|
from classiq.qmod.declaration_inferrer import python_type_to_qmod
|
14
14
|
from classiq.qmod.model_state_container import ModelStateContainer
|
15
|
-
from classiq.qmod.qmod_parameter import
|
15
|
+
from classiq.qmod.qmod_parameter import CParam, CParamList, CParamStruct
|
16
16
|
|
17
17
|
|
18
18
|
class QConstant:
|
@@ -61,22 +61,22 @@ class QConstant:
|
|
61
61
|
value=Expression(expr=expr),
|
62
62
|
)
|
63
63
|
|
64
|
-
def __getattr__(self, name: str) ->
|
64
|
+
def __getattr__(self, name: str) -> CParam:
|
65
65
|
self.add_to_model()
|
66
66
|
|
67
67
|
py_type = type(self._value)
|
68
68
|
if (
|
69
69
|
QConstant.CURRENT_QMODULE is None
|
70
70
|
or not inspect.isclass(py_type)
|
71
|
-
or not issubclass(py_type,
|
71
|
+
or not issubclass(py_type, CStructBase)
|
72
72
|
):
|
73
73
|
return self.__getattribute__(name)
|
74
74
|
|
75
|
-
return
|
75
|
+
return CParamStruct.get_field(
|
76
76
|
QConstant.CURRENT_QMODULE, self.name, py_type.__name__, name
|
77
77
|
)
|
78
78
|
|
79
|
-
def __getitem__(self, item: Any) ->
|
79
|
+
def __getitem__(self, item: Any) -> CParam:
|
80
80
|
self.add_to_model()
|
81
81
|
|
82
82
|
assert QConstant.CURRENT_QMODULE is not None
|
@@ -90,7 +90,7 @@ class QConstant:
|
|
90
90
|
if not isinstance(qmod_type, (ClassicalList, ClassicalArray)):
|
91
91
|
raise ClassiqError("Invalid subscript to non-list constant")
|
92
92
|
|
93
|
-
return
|
93
|
+
return CParamList(
|
94
94
|
self.name,
|
95
95
|
qmod_type,
|
96
96
|
QConstant.CURRENT_QMODULE,
|