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
@@ -1,22 +1,39 @@
|
|
1
|
-
|
1
|
+
import inspect
|
2
|
+
import sys
|
3
|
+
import warnings
|
4
|
+
from types import FrameType
|
5
|
+
from typing import Any, Callable, Final, List, Mapping, Union, overload
|
2
6
|
|
3
7
|
from classiq.interface.generator.expressions.expression import Expression
|
8
|
+
from classiq.interface.generator.functions.builtins.internal_operators import (
|
9
|
+
REPEAT_OPERATOR,
|
10
|
+
)
|
4
11
|
from classiq.interface.model.bind_operation import BindOperation
|
12
|
+
from classiq.interface.model.classical_if import ClassicalIf
|
13
|
+
from classiq.interface.model.control import Control
|
5
14
|
from classiq.interface.model.inplace_binary_operation import (
|
6
15
|
BinaryOperation,
|
7
16
|
InplaceBinaryOperation,
|
8
17
|
)
|
9
|
-
from classiq.interface.model.
|
18
|
+
from classiq.interface.model.invert import Invert
|
19
|
+
from classiq.interface.model.power import Power
|
20
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
10
21
|
from classiq.interface.model.quantum_function_declaration import (
|
11
22
|
QuantumOperandDeclaration,
|
12
23
|
)
|
13
|
-
from classiq.interface.model.
|
14
|
-
from classiq.interface.model.
|
24
|
+
from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
|
25
|
+
from classiq.interface.model.repeat import Repeat
|
26
|
+
from classiq.interface.model.statement_block import StatementBlock
|
27
|
+
from classiq.interface.model.within_apply_operation import WithinApply
|
15
28
|
|
16
|
-
from classiq.
|
29
|
+
from classiq.exceptions import ClassiqValueError
|
30
|
+
from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QVar
|
17
31
|
from classiq.qmod.quantum_callable import QCallable
|
18
32
|
from classiq.qmod.quantum_expandable import prepare_arg
|
19
33
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
34
|
+
from classiq.qmod.utilities import get_source_ref
|
35
|
+
|
36
|
+
_MISSING_VALUE: Final[int] = -1
|
20
37
|
|
21
38
|
|
22
39
|
def bind(
|
@@ -24,6 +41,7 @@ def bind(
|
|
24
41
|
destination: Union[Output[QVar], List[Output[QVar]]],
|
25
42
|
) -> None:
|
26
43
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
44
|
+
source_ref = get_source_ref(sys._getframe(1))
|
27
45
|
if not isinstance(source, list):
|
28
46
|
source = [source]
|
29
47
|
if not isinstance(destination, list):
|
@@ -32,32 +50,104 @@ def bind(
|
|
32
50
|
BindOperation(
|
33
51
|
in_handles=[src_var.get_handle_binding() for src_var in source],
|
34
52
|
out_handles=[dst_var.get_handle_binding() for dst_var in destination],
|
53
|
+
source_ref=source_ref,
|
35
54
|
)
|
36
55
|
)
|
37
56
|
|
38
57
|
|
39
|
-
def
|
40
|
-
condition: SymbolicExpr,
|
58
|
+
def if_(
|
59
|
+
condition: SymbolicExpr,
|
60
|
+
then: Union[QCallable, Callable[[], None]],
|
61
|
+
else_: Union[QCallable, Callable[[], None], int] = _MISSING_VALUE,
|
41
62
|
) -> None:
|
63
|
+
_validate_operand(then)
|
64
|
+
if else_ != _MISSING_VALUE:
|
65
|
+
_validate_operand(else_)
|
42
66
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
67
|
+
source_ref = get_source_ref(sys._getframe(1))
|
43
68
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
44
|
-
|
45
|
-
|
46
|
-
then=
|
69
|
+
ClassicalIf(
|
70
|
+
condition=Expression(expr=str(condition)),
|
71
|
+
then=_operand_to_body(then),
|
72
|
+
else_=_operand_to_body(else_) if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
|
73
|
+
source_ref=source_ref,
|
47
74
|
)
|
48
75
|
)
|
49
76
|
|
50
77
|
|
78
|
+
@overload
|
79
|
+
def control(
|
80
|
+
ctrl: Union[QBit, QArray[QBit]], operand: Union[QCallable, Callable[[], None]]
|
81
|
+
) -> None:
|
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)
|
116
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
117
|
+
source_ref = get_source_ref(sys._getframe(1))
|
118
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
119
|
+
Control(
|
120
|
+
expression=Expression(expr=str(ctrl)),
|
121
|
+
body=_operand_to_body(operand),
|
122
|
+
source_ref=source_ref,
|
123
|
+
)
|
124
|
+
)
|
125
|
+
|
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
|
+
|
51
139
|
def inplace_add(
|
52
140
|
value: QNum,
|
53
141
|
target: QNum,
|
54
142
|
) -> None:
|
55
143
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
144
|
+
source_ref = get_source_ref(sys._getframe(1))
|
56
145
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
57
146
|
InplaceBinaryOperation(
|
58
147
|
target=target.get_handle_binding(),
|
59
148
|
value=value.get_handle_binding(),
|
60
149
|
operation=BinaryOperation.Addition,
|
150
|
+
source_ref=source_ref,
|
61
151
|
)
|
62
152
|
)
|
63
153
|
|
@@ -67,11 +157,13 @@ def inplace_xor(
|
|
67
157
|
target: QNum,
|
68
158
|
) -> None:
|
69
159
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
160
|
+
source_ref = get_source_ref(sys._getframe(1))
|
70
161
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
71
162
|
InplaceBinaryOperation(
|
72
163
|
target=target.get_handle_binding(),
|
73
164
|
value=value.get_handle_binding(),
|
74
165
|
operation=BinaryOperation.Xor,
|
166
|
+
source_ref=source_ref,
|
75
167
|
)
|
76
168
|
)
|
77
169
|
|
@@ -80,25 +172,134 @@ def within_apply(
|
|
80
172
|
compute: Callable[[], None],
|
81
173
|
action: Callable[[], None],
|
82
174
|
) -> None:
|
175
|
+
_validate_operand(compute)
|
176
|
+
_validate_operand(action)
|
177
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
178
|
+
source_ref = get_source_ref(sys._getframe(1))
|
179
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
180
|
+
WithinApply(
|
181
|
+
compute=_operand_to_body(compute),
|
182
|
+
action=_operand_to_body(action),
|
183
|
+
source_ref=source_ref,
|
184
|
+
)
|
185
|
+
)
|
186
|
+
|
187
|
+
|
188
|
+
def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) -> None:
|
189
|
+
_validate_operand(iteration)
|
190
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
191
|
+
source_ref = get_source_ref(sys._getframe(1))
|
192
|
+
iteration_operand = prepare_arg(
|
193
|
+
REPEAT_OPERATOR.operand_declarations["iteration"], iteration
|
194
|
+
)
|
195
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
196
|
+
Repeat(
|
197
|
+
iter_var=inspect.getfullargspec(iteration).args[0],
|
198
|
+
count=Expression(expr=str(count)),
|
199
|
+
body=iteration_operand.body,
|
200
|
+
source_ref=source_ref,
|
201
|
+
)
|
202
|
+
)
|
203
|
+
|
204
|
+
|
205
|
+
def power(
|
206
|
+
power: Union[SymbolicExpr, int],
|
207
|
+
operand: Union[QCallable, Callable[[], None]],
|
208
|
+
) -> None:
|
209
|
+
_validate_operand(operand)
|
83
210
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
211
|
+
source_ref = get_source_ref(sys._getframe(1))
|
84
212
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
85
|
-
|
86
|
-
|
87
|
-
|
213
|
+
Power(
|
214
|
+
power=Expression(expr=str(power)),
|
215
|
+
body=_operand_to_body(operand),
|
216
|
+
source_ref=source_ref,
|
88
217
|
)
|
89
218
|
)
|
90
219
|
|
91
220
|
|
92
|
-
def
|
93
|
-
|
221
|
+
def invert(
|
222
|
+
operand: Union[QCallable, Callable[[], None]],
|
223
|
+
) -> None:
|
224
|
+
_validate_operand(operand)
|
225
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
226
|
+
source_ref = get_source_ref(sys._getframe(1))
|
227
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
228
|
+
Invert(body=_operand_to_body(operand), source_ref=source_ref)
|
229
|
+
)
|
230
|
+
|
231
|
+
|
232
|
+
def _validate_operand(operand: Any) -> None:
|
233
|
+
if operand is not None:
|
234
|
+
return
|
235
|
+
currentframe: FrameType = inspect.currentframe() # type: ignore[assignment]
|
236
|
+
operation_frame: FrameType = currentframe.f_back # type: ignore[assignment]
|
237
|
+
operation_frame_info: inspect.Traceback = inspect.getframeinfo(operation_frame)
|
238
|
+
operation_name: str = operation_frame_info.function
|
239
|
+
|
240
|
+
context = operation_frame_info.code_context
|
241
|
+
assert context is not None
|
242
|
+
operand_arg_name = context[0].split("_validate_operand(")[1].split(")")[0]
|
243
|
+
|
244
|
+
error_message = (
|
245
|
+
f"{operation_name} is missing required argument for {operand_arg_name}"
|
246
|
+
)
|
247
|
+
error_message += _get_operand_hint(
|
248
|
+
operation_name=operation_name,
|
249
|
+
operand_arg_name=operand_arg_name,
|
250
|
+
params=inspect.signature(operation_frame.f_globals[operation_name]).parameters,
|
251
|
+
)
|
252
|
+
raise ClassiqValueError(error_message)
|
253
|
+
|
254
|
+
|
255
|
+
def _get_operand_hint_args(
|
256
|
+
params: Mapping[str, inspect.Parameter], operand_arg_name: str, operand_value: str
|
257
|
+
) -> str:
|
258
|
+
return ", ".join(
|
259
|
+
[
|
260
|
+
(
|
261
|
+
f"{param.name}={operand_value}"
|
262
|
+
if param.name == operand_arg_name
|
263
|
+
else f"{param.name}=..."
|
264
|
+
)
|
265
|
+
for param in params.values()
|
266
|
+
]
|
267
|
+
)
|
268
|
+
|
269
|
+
|
270
|
+
def _get_operand_hint(
|
271
|
+
operation_name: str, operand_arg_name: str, params: Mapping[str, inspect.Parameter]
|
272
|
+
) -> str:
|
273
|
+
return (
|
274
|
+
f"\nHint: To create an operand, do not call quantum gates directly "
|
275
|
+
f"`{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'H(q)')})`. "
|
276
|
+
f"Instead, use a lambda function "
|
277
|
+
f"`{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'lambda: H(q)')})` "
|
278
|
+
f"or a quantum function "
|
279
|
+
f"`{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'my_func')})`"
|
280
|
+
)
|
281
|
+
|
282
|
+
|
283
|
+
def _operand_to_body(callable_: Union[QCallable, Callable[[], None]]) -> StatementBlock:
|
284
|
+
to_operand = prepare_arg(QuantumOperandDeclaration(name=""), callable_)
|
285
|
+
if isinstance(to_operand, str):
|
286
|
+
return [QuantumFunctionCall(function=to_operand)]
|
287
|
+
elif isinstance(to_operand, QuantumLambdaFunction):
|
288
|
+
return to_operand.body
|
289
|
+
else:
|
290
|
+
raise ValueError(f"Unexpected operand type: {type(to_operand)}")
|
94
291
|
|
95
292
|
|
96
293
|
__all__ = [
|
97
294
|
"bind",
|
98
|
-
"
|
295
|
+
"control",
|
296
|
+
"invert",
|
297
|
+
"if_",
|
99
298
|
"inplace_add",
|
100
299
|
"inplace_xor",
|
300
|
+
"power",
|
101
301
|
"within_apply",
|
302
|
+
"repeat",
|
102
303
|
]
|
103
304
|
|
104
305
|
|
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):
|