classiq 0.66.1__py3-none-any.whl → 0.68.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/_internals/api_wrapper.py +5 -1
- classiq/_internals/async_utils.py +1 -1
- classiq/_internals/authentication/password_manager.py +1 -1
- classiq/_internals/client.py +1 -1
- classiq/applications/finance/finance_model_constructor.py +9 -0
- classiq/applications/grover/grover_model_constructor.py +10 -0
- classiq/applications/qnn/qlayer.py +8 -2
- classiq/applications/qsvm/qsvm_model_constructor.py +9 -0
- classiq/execution/execution_session.py +7 -3
- classiq/executor.py +7 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/ast_node.py +1 -1
- classiq/interface/chemistry/operator.py +1 -1
- classiq/interface/debug_info/debug_info.py +27 -0
- classiq/interface/exceptions.py +2 -5
- classiq/interface/generator/arith/argument_utils.py +1 -1
- classiq/interface/generator/arith/arithmetic.py +99 -2
- classiq/interface/generator/arith/arithmetic_expression_parser.py +1 -1
- classiq/interface/generator/arith/binary_ops.py +3 -0
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -0
- classiq/interface/generator/functions/type_name.py +2 -2
- classiq/interface/generator/generated_circuit_data.py +38 -3
- classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
- classiq/interface/generator/hva.py +1 -1
- classiq/interface/generator/model/preferences/preferences.py +8 -1
- classiq/interface/generator/quantum_program.py +18 -1
- classiq/interface/generator/reset.py +14 -0
- classiq/interface/generator/types/enum_declaration.py +33 -2
- classiq/interface/generator/ucc.py +1 -1
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/classical_if.py +2 -2
- classiq/interface/model/control.py +2 -2
- classiq/interface/model/invert.py +2 -2
- classiq/interface/model/power.py +2 -2
- classiq/interface/model/quantum_function_call.py +4 -0
- classiq/interface/model/quantum_statement.py +13 -0
- classiq/interface/model/repeat.py +2 -2
- classiq/interface/model/statement_block.py +1 -1
- classiq/interface/model/within_apply_operation.py +2 -2
- classiq/model_expansions/atomic_expression_functions_defs.py +2 -1
- classiq/model_expansions/capturing/captured_vars.py +184 -54
- classiq/model_expansions/closure.py +6 -3
- classiq/model_expansions/evaluators/control.py +14 -38
- classiq/model_expansions/function_builder.py +19 -14
- classiq/model_expansions/generative_functions.py +7 -11
- classiq/model_expansions/interpreters/base_interpreter.py +14 -5
- classiq/model_expansions/interpreters/generative_interpreter.py +87 -26
- classiq/model_expansions/quantum_operations/allocate.py +9 -3
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +52 -0
- classiq/model_expansions/quantum_operations/bind.py +67 -14
- classiq/model_expansions/quantum_operations/block_evaluator.py +76 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +79 -10
- classiq/model_expansions/quantum_operations/classicalif.py +10 -6
- classiq/model_expansions/quantum_operations/composite_emitter.py +27 -0
- classiq/model_expansions/quantum_operations/emitter.py +24 -3
- classiq/model_expansions/quantum_operations/expression_evaluator.py +33 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +28 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +3 -2
- classiq/model_expansions/quantum_operations/repeat.py +9 -3
- classiq/model_expansions/quantum_operations/variable_decleration.py +13 -2
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +1 -1
- classiq/open_library/functions/__init__.py +1 -2
- classiq/open_library/functions/amplitude_amplification.py +12 -9
- classiq/open_library/functions/discrete_sine_cosine_transform.py +16 -13
- classiq/open_library/functions/grover.py +11 -15
- classiq/open_library/functions/modular_exponentiation.py +7 -13
- classiq/open_library/functions/state_preparation.py +16 -17
- classiq/open_library/functions/swap_test.py +1 -1
- classiq/open_library/functions/utility_functions.py +10 -2
- classiq/qmod/builtins/functions/__init__.py +3 -0
- classiq/qmod/builtins/functions/chemistry.py +6 -38
- classiq/qmod/builtins/functions/mid_circuit_measurement.py +15 -0
- classiq/qmod/quantum_expandable.py +30 -6
- classiq/qmod/quantum_function.py +4 -0
- classiq/qmod/semantics/annotation/call_annotation.py +8 -2
- classiq/qmod/semantics/annotation/model_annotation.py +9 -0
- classiq/qmod/semantics/error_manager.py +0 -6
- classiq/qmod/semantics/static_semantics_visitor.py +0 -347
- classiq/qmod/semantics/validation/types_validation.py +1 -1
- classiq/qmod/symbolic.py +2 -1
- classiq/qmod/utilities.py +2 -1
- classiq/qmod/write_qmod.py +10 -7
- classiq/synthesis.py +20 -7
- {classiq-0.66.1.dist-info → classiq-0.68.0.dist-info}/METADATA +1 -1
- {classiq-0.66.1.dist-info → classiq-0.68.0.dist-info}/RECORD +86 -81
- classiq/model_expansions/quantum_operations/shallow_emitter.py +0 -166
- classiq/qmod/semantics/validation/func_call_validation.py +0 -99
- classiq/qmod/semantics/validation/handle_validation.py +0 -85
- {classiq-0.66.1.dist-info → classiq-0.68.0.dist-info}/WHEEL +0 -0
@@ -1,347 +0,0 @@
|
|
1
|
-
import ast
|
2
|
-
from collections.abc import Iterator, Mapping, Sequence
|
3
|
-
from contextlib import contextmanager
|
4
|
-
from typing import (
|
5
|
-
Optional,
|
6
|
-
)
|
7
|
-
|
8
|
-
from classiq.interface.exceptions import ClassiqSemanticError
|
9
|
-
from classiq.interface.generator.expressions.expression import Expression
|
10
|
-
from classiq.interface.generator.function_params import PortDirection
|
11
|
-
from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
|
12
|
-
from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
|
13
|
-
from classiq.interface.generator.functions.port_declaration import (
|
14
|
-
PortDeclarationDirection,
|
15
|
-
)
|
16
|
-
from classiq.interface.model.handle_binding import (
|
17
|
-
FieldHandleBinding,
|
18
|
-
HandleBinding,
|
19
|
-
SlicedHandleBinding,
|
20
|
-
SubscriptHandleBinding,
|
21
|
-
)
|
22
|
-
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
23
|
-
from classiq.interface.model.model import Model
|
24
|
-
from classiq.interface.model.model_visitor import ModelVisitor
|
25
|
-
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
26
|
-
from classiq.interface.model.port_declaration import PortDeclaration
|
27
|
-
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
28
|
-
QuantumExpressionOperation,
|
29
|
-
)
|
30
|
-
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
31
|
-
from classiq.interface.model.quantum_function_declaration import (
|
32
|
-
QuantumFunctionDeclaration,
|
33
|
-
QuantumOperandDeclaration,
|
34
|
-
)
|
35
|
-
from classiq.interface.model.quantum_lambda_function import (
|
36
|
-
QuantumLambdaFunction,
|
37
|
-
)
|
38
|
-
from classiq.interface.model.quantum_statement import HandleMetadata, QuantumOperation
|
39
|
-
from classiq.interface.model.validation_handle import HandleState
|
40
|
-
from classiq.interface.model.variable_declaration_statement import (
|
41
|
-
VariableDeclarationStatement,
|
42
|
-
)
|
43
|
-
from classiq.interface.model.within_apply_operation import WithinApply
|
44
|
-
|
45
|
-
from classiq.model_expansions.visitors.variable_references import VarRefCollector
|
46
|
-
from classiq.qmod.builtins.functions import (
|
47
|
-
BUILTIN_FUNCTION_DECLARATIONS,
|
48
|
-
)
|
49
|
-
from classiq.qmod.semantics.annotation.call_annotation import resolve_function_calls
|
50
|
-
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
51
|
-
from classiq.qmod.semantics.error_manager import ErrorManager
|
52
|
-
from classiq.qmod.semantics.lambdas import get_renamed_parameters
|
53
|
-
from classiq.qmod.semantics.validation.func_call_validation import (
|
54
|
-
check_no_overlapping_quantum_args,
|
55
|
-
validate_call_arguments,
|
56
|
-
)
|
57
|
-
from classiq.qmod.semantics.validation.handle_validation import resolve_handle
|
58
|
-
|
59
|
-
HANDLE_BINDING_PART_MESSAGE = {
|
60
|
-
SubscriptHandleBinding: "array subscript",
|
61
|
-
SlicedHandleBinding: "array slice",
|
62
|
-
FieldHandleBinding: "field access",
|
63
|
-
}
|
64
|
-
|
65
|
-
|
66
|
-
class StaticScope:
|
67
|
-
def __init__(
|
68
|
-
self,
|
69
|
-
parameters: list[str],
|
70
|
-
operands: dict[str, QuantumOperandDeclaration],
|
71
|
-
variables_to_states: dict[str, HandleState],
|
72
|
-
variables_to_types: dict[str, ConcreteQuantumType],
|
73
|
-
) -> None:
|
74
|
-
self.parameters = parameters
|
75
|
-
self.operands = operands
|
76
|
-
self.variable_states = variables_to_states
|
77
|
-
self.variables_to_types = variables_to_types
|
78
|
-
|
79
|
-
|
80
|
-
class StaticSemanticsVisitor(ModelVisitor):
|
81
|
-
def __init__(
|
82
|
-
self,
|
83
|
-
functions_dict: Mapping[str, QuantumFunctionDeclaration],
|
84
|
-
constants: list[str],
|
85
|
-
) -> None:
|
86
|
-
self._scope: list[StaticScope] = []
|
87
|
-
self._error_manager = ErrorManager()
|
88
|
-
self._functions_dict = functions_dict
|
89
|
-
self._constants = constants
|
90
|
-
|
91
|
-
@property
|
92
|
-
def current_scope(self) -> StaticScope:
|
93
|
-
return self._scope[-1]
|
94
|
-
|
95
|
-
@contextmanager
|
96
|
-
def scoped_visit(self, scope: StaticScope) -> Iterator[None]:
|
97
|
-
self._scope.append(scope)
|
98
|
-
yield
|
99
|
-
self._scope.pop()
|
100
|
-
|
101
|
-
def visit_Model(self, model: Model) -> None:
|
102
|
-
self.visit_BaseModel(model)
|
103
|
-
|
104
|
-
def visit_NativeFunctionDefinition(
|
105
|
-
self, func_def: NativeFunctionDefinition
|
106
|
-
) -> None:
|
107
|
-
scope = StaticScope(
|
108
|
-
parameters=list(func_def.param_names) + self._constants,
|
109
|
-
operands=dict(func_def.operand_declarations_dict),
|
110
|
-
variables_to_states=initialize_variables_to_state(
|
111
|
-
func_def.port_declarations
|
112
|
-
),
|
113
|
-
variables_to_types={
|
114
|
-
port.name: port.quantum_type for port in func_def.port_declarations
|
115
|
-
},
|
116
|
-
)
|
117
|
-
with self.scoped_visit(scope), self._error_manager.call(func_def.name):
|
118
|
-
if len(func_def.body) == 0:
|
119
|
-
return
|
120
|
-
self.visit(func_def.body)
|
121
|
-
with self._error_manager.node_context(func_def.body[-1]):
|
122
|
-
for port_decl in func_def.port_declarations:
|
123
|
-
handle_state = self.current_scope.variable_states[port_decl.name]
|
124
|
-
expected_terminal_state = EXPECTED_TERMINAL_STATES.get(
|
125
|
-
port_decl.direction
|
126
|
-
)
|
127
|
-
if (
|
128
|
-
expected_terminal_state is not None
|
129
|
-
and handle_state is not expected_terminal_state
|
130
|
-
):
|
131
|
-
self._error_manager.add_error(
|
132
|
-
f"At the end of the function, variable {port_decl.name!r} is expected to be {expected_terminal_state.name.lower()} but it isn't"
|
133
|
-
)
|
134
|
-
|
135
|
-
def visit_WithinApply(self, within_apply: WithinApply) -> None:
|
136
|
-
initial_variables_to_state = self.current_scope.variable_states.copy()
|
137
|
-
scope = StaticScope(
|
138
|
-
parameters=self.current_scope.parameters,
|
139
|
-
operands=self.current_scope.operands,
|
140
|
-
variables_to_states=self.current_scope.variable_states.copy(),
|
141
|
-
variables_to_types=self.current_scope.variables_to_types.copy(),
|
142
|
-
)
|
143
|
-
with self.scoped_visit(scope):
|
144
|
-
self.visit(within_apply.compute)
|
145
|
-
compute_captured_variables = {
|
146
|
-
var
|
147
|
-
for var, state in self.current_scope.variable_states.items()
|
148
|
-
if var in initial_variables_to_state
|
149
|
-
and state != initial_variables_to_state[var]
|
150
|
-
}
|
151
|
-
self.visit(within_apply.action)
|
152
|
-
variables_to_state = self.current_scope.variable_states.copy()
|
153
|
-
self.current_scope.variable_states.update(
|
154
|
-
{
|
155
|
-
var: state
|
156
|
-
for var, state in variables_to_state.items()
|
157
|
-
if var in self.current_scope.variable_states
|
158
|
-
and var not in compute_captured_variables
|
159
|
-
}
|
160
|
-
)
|
161
|
-
|
162
|
-
def visit_QuantumOperation(self, op: QuantumOperation) -> None:
|
163
|
-
with self._error_manager.node_context(op):
|
164
|
-
if isinstance(op, QuantumFunctionCall):
|
165
|
-
validate_call_arguments(
|
166
|
-
op,
|
167
|
-
{
|
168
|
-
**self._functions_dict,
|
169
|
-
**self.current_scope.operands,
|
170
|
-
},
|
171
|
-
)
|
172
|
-
elif isinstance(op, InplaceBinaryOperation) and isinstance(
|
173
|
-
op.value, HandleBinding
|
174
|
-
):
|
175
|
-
check_no_overlapping_quantum_args(
|
176
|
-
[op.target, op.value], op.operation.value
|
177
|
-
)
|
178
|
-
self._handle_inputs(op.readable_inputs)
|
179
|
-
self._handle_outputs(op.readable_outputs)
|
180
|
-
self._handle_inouts(op.readable_inouts)
|
181
|
-
self.generic_visit(op)
|
182
|
-
|
183
|
-
def visit_VariableDeclarationStatement(
|
184
|
-
self, declaration: VariableDeclarationStatement
|
185
|
-
) -> None:
|
186
|
-
handle_wiring_state = self.current_scope.variable_states.get(declaration.name)
|
187
|
-
if handle_wiring_state is not None:
|
188
|
-
self._error_manager.add_error(
|
189
|
-
f"Trying to declare a variable of the same name as previously declared variable {declaration.name}"
|
190
|
-
)
|
191
|
-
return
|
192
|
-
|
193
|
-
self.current_scope.variable_states[declaration.name] = HandleState.UNINITIALIZED
|
194
|
-
self.current_scope.variables_to_types[declaration.name] = (
|
195
|
-
declaration.quantum_type
|
196
|
-
)
|
197
|
-
|
198
|
-
def visit_QuantumLambdaFunction(self, lambda_func: QuantumLambdaFunction) -> None:
|
199
|
-
renamed_parameters, renamed_operands, renamed_ports = get_renamed_parameters(
|
200
|
-
lambda_func
|
201
|
-
)
|
202
|
-
scope = StaticScope(
|
203
|
-
parameters=self.current_scope.parameters + renamed_parameters,
|
204
|
-
operands={**self.current_scope.operands, **renamed_operands},
|
205
|
-
variables_to_states={
|
206
|
-
**self.current_scope.variable_states.copy(),
|
207
|
-
**initialize_variables_to_state(renamed_ports),
|
208
|
-
},
|
209
|
-
variables_to_types=self.current_scope.variables_to_types
|
210
|
-
| {port.name: port.quantum_type for port in renamed_ports},
|
211
|
-
)
|
212
|
-
with self.scoped_visit(scope):
|
213
|
-
self.generic_visit(lambda_func)
|
214
|
-
|
215
|
-
def visit_HandleBinding(self, handle: HandleBinding) -> None:
|
216
|
-
resolve_handle(self.current_scope, handle)
|
217
|
-
|
218
|
-
def visit_Expression(self, expr: Expression) -> None:
|
219
|
-
if len(self._scope) == 0:
|
220
|
-
return
|
221
|
-
vrc = VarRefCollector(ignore_duplicated_handles=True, unevaluated=True)
|
222
|
-
vrc.visit(ast.parse(expr.expr))
|
223
|
-
handles = [
|
224
|
-
HandleMetadata(handle=handle)
|
225
|
-
for handle in vrc.var_handles
|
226
|
-
if handle.name in self.current_scope.variable_states
|
227
|
-
and (
|
228
|
-
not isinstance(handle, FieldHandleBinding)
|
229
|
-
or handle.field not in CLASSICAL_ATTRIBUTES
|
230
|
-
)
|
231
|
-
]
|
232
|
-
self._handle_inouts(handles)
|
233
|
-
|
234
|
-
def visit_QuantumExpressionOperation(self, op: QuantumExpressionOperation) -> None:
|
235
|
-
self.visit_Expression(op.expression)
|
236
|
-
self.visit_QuantumOperation(op)
|
237
|
-
|
238
|
-
def _handle_state_changing_ios(
|
239
|
-
self,
|
240
|
-
ios: Sequence[HandleMetadata],
|
241
|
-
state: HandleState,
|
242
|
-
state_change_verb: str,
|
243
|
-
) -> None:
|
244
|
-
for handle_metadata in ios:
|
245
|
-
handle_binding = handle_metadata.handle
|
246
|
-
if isinstance(
|
247
|
-
handle_binding,
|
248
|
-
(SubscriptHandleBinding, SlicedHandleBinding, FieldHandleBinding),
|
249
|
-
):
|
250
|
-
self._error_manager.add_error(
|
251
|
-
f"Cannot use {HANDLE_BINDING_PART_MESSAGE[type(handle_binding)]} of variable {handle_binding.name!r} in {state_change_verb} context"
|
252
|
-
)
|
253
|
-
continue
|
254
|
-
handle_wiring_state = self.current_scope.variable_states.get(
|
255
|
-
handle_binding.name
|
256
|
-
)
|
257
|
-
if handle_wiring_state is not state:
|
258
|
-
state_prefix = (
|
259
|
-
""
|
260
|
-
if handle_wiring_state is None
|
261
|
-
else f"{handle_wiring_state.name.lower()} "
|
262
|
-
)
|
263
|
-
location = (
|
264
|
-
f" {handle_metadata.readable_location}"
|
265
|
-
if handle_metadata.readable_location is not None
|
266
|
-
else ""
|
267
|
-
)
|
268
|
-
self._error_manager.add_error(
|
269
|
-
f"Cannot use {state_prefix}quantum variable {handle_binding.name!r}"
|
270
|
-
f"{location}"
|
271
|
-
)
|
272
|
-
|
273
|
-
self.current_scope.variable_states[handle_binding.name] = ~state
|
274
|
-
|
275
|
-
def _handle_inputs(self, inputs: Sequence[HandleMetadata]) -> None:
|
276
|
-
self._handle_state_changing_ios(
|
277
|
-
inputs, HandleState.INITIALIZED, "uninitialization"
|
278
|
-
)
|
279
|
-
|
280
|
-
def _handle_outputs(self, outputs: Sequence[HandleMetadata]) -> None:
|
281
|
-
self._handle_state_changing_ios(
|
282
|
-
outputs, HandleState.UNINITIALIZED, "initialization"
|
283
|
-
)
|
284
|
-
|
285
|
-
def _handle_inouts(self, inouts: Sequence[HandleMetadata]) -> None:
|
286
|
-
for handle_metadata in inouts:
|
287
|
-
handle_binding = handle_metadata.handle
|
288
|
-
|
289
|
-
if handle_binding.name not in self.current_scope.variable_states:
|
290
|
-
ErrorManager().add_error(
|
291
|
-
f"Variable {handle_binding.name!r} is not defined"
|
292
|
-
)
|
293
|
-
return
|
294
|
-
handle_wiring_state = self.current_scope.variable_states[
|
295
|
-
handle_binding.name
|
296
|
-
]
|
297
|
-
|
298
|
-
if handle_wiring_state is not HandleState.INITIALIZED:
|
299
|
-
state_prefix = (
|
300
|
-
""
|
301
|
-
if handle_wiring_state is None
|
302
|
-
else f"{handle_wiring_state.name.lower()} "
|
303
|
-
)
|
304
|
-
location = (
|
305
|
-
f" {handle_metadata.readable_location}"
|
306
|
-
if handle_metadata.readable_location is not None
|
307
|
-
else ""
|
308
|
-
)
|
309
|
-
self._error_manager.add_error(
|
310
|
-
f"Cannot use {state_prefix}quantum variable {handle_binding.name!r}"
|
311
|
-
f"{location}"
|
312
|
-
)
|
313
|
-
|
314
|
-
|
315
|
-
def static_semantics_analysis_pass(
|
316
|
-
model: Model, error_type: Optional[type[Exception]] = ClassiqSemanticError
|
317
|
-
) -> None:
|
318
|
-
QStructAnnotator().visit(model)
|
319
|
-
functions = {**BUILTIN_FUNCTION_DECLARATIONS, **model.function_dict}
|
320
|
-
resolve_function_calls(model, functions)
|
321
|
-
StaticSemanticsVisitor(
|
322
|
-
functions,
|
323
|
-
[const.name for const in model.constants],
|
324
|
-
).visit(model)
|
325
|
-
if error_type is not None:
|
326
|
-
ErrorManager().report_errors(error_type)
|
327
|
-
|
328
|
-
|
329
|
-
EXPECTED_TERMINAL_STATES: dict[PortDeclarationDirection, HandleState] = {
|
330
|
-
PortDeclarationDirection.Output: HandleState.INITIALIZED,
|
331
|
-
PortDeclarationDirection.Inout: HandleState.INITIALIZED,
|
332
|
-
}
|
333
|
-
|
334
|
-
|
335
|
-
def initialize_variables_to_state(
|
336
|
-
port_declarations: Sequence[PortDeclaration],
|
337
|
-
) -> dict[str, HandleState]:
|
338
|
-
variables_to_state: dict[str, HandleState] = dict()
|
339
|
-
|
340
|
-
for port_decl in port_declarations:
|
341
|
-
variables_to_state[port_decl.name] = (
|
342
|
-
HandleState.INITIALIZED
|
343
|
-
if port_decl.direction.includes_port_direction(PortDirection.Input)
|
344
|
-
else HandleState.UNINITIALIZED
|
345
|
-
)
|
346
|
-
|
347
|
-
return variables_to_state
|
@@ -16,7 +16,7 @@ TYPE_EXISTS_ERROR_MESSAGE = "Type {!r} already exists"
|
|
16
16
|
|
17
17
|
|
18
18
|
def check_duplicate_types(
|
19
|
-
types: Sequence[Union[EnumDeclaration, StructDeclaration, QStructDeclaration]]
|
19
|
+
types: Sequence[Union[EnumDeclaration, StructDeclaration, QStructDeclaration]],
|
20
20
|
) -> None:
|
21
21
|
known_types = {type_.name for type_ in BUILTIN_ENUM_DECLARATIONS.values()}
|
22
22
|
known_types |= {type_.name for type_ in BUILTIN_STRUCT_DECLARATIONS.values()}
|
classiq/qmod/symbolic.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import sys
|
2
|
+
from collections.abc import Sequence
|
2
3
|
from typing import (
|
3
4
|
TYPE_CHECKING,
|
4
5
|
Any,
|
@@ -296,7 +297,7 @@ def sum(arr: SymbolicTypes) -> CParamScalar:
|
|
296
297
|
|
297
298
|
|
298
299
|
def subscript(
|
299
|
-
amplitudes: Union[
|
300
|
+
amplitudes: Union[Sequence[Union[float, CReal, CParamScalar]], CArray[CReal]],
|
300
301
|
index: QNum,
|
301
302
|
) -> CParamScalar:
|
302
303
|
return CParamScalar(expr=f"{amplitudes}[{index}]")
|
classiq/qmod/utilities.py
CHANGED
@@ -3,6 +3,7 @@ import inspect
|
|
3
3
|
import itertools
|
4
4
|
import keyword
|
5
5
|
import sys
|
6
|
+
from collections.abc import Iterable
|
6
7
|
from enum import Enum as PythonEnum
|
7
8
|
from types import FrameType
|
8
9
|
from typing import Any, ForwardRef, Literal, Optional, get_args, get_origin, overload
|
@@ -101,7 +102,7 @@ def qmod_val_to_expr_str(val: Any) -> str:
|
|
101
102
|
)
|
102
103
|
return f"struct_literal({val.struct_declaration.name}, {kwargs_str})"
|
103
104
|
|
104
|
-
if isinstance(val,
|
105
|
+
if isinstance(val, Iterable):
|
105
106
|
elements_str = ", ".join([qmod_val_to_expr_str(elem) for elem in val])
|
106
107
|
return f"[{elements_str}]"
|
107
108
|
|
classiq/qmod/write_qmod.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
import json
|
2
2
|
from pathlib import Path
|
3
|
-
from typing import Optional
|
3
|
+
from typing import Optional, Union
|
4
4
|
|
5
5
|
from classiq.interface.model.model import Model, SerializedModel
|
6
6
|
|
7
7
|
from classiq.qmod.native.pretty_printer import DSLPrettyPrinter
|
8
|
+
from classiq.qmod.quantum_function import GenerativeQFunc, QFunc
|
8
9
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
9
10
|
|
10
11
|
_QMOD_SUFFIX = "qmod"
|
@@ -12,7 +13,7 @@ _SYNTHESIS_OPTIONS_SUFFIX = "synthesis_options.json"
|
|
12
13
|
|
13
14
|
|
14
15
|
def write_qmod(
|
15
|
-
|
16
|
+
model: Union[SerializedModel, QFunc, GenerativeQFunc],
|
16
17
|
name: str,
|
17
18
|
directory: Optional[Path] = None,
|
18
19
|
decimal_precision: int = DEFAULT_DECIMAL_PRECISION,
|
@@ -22,7 +23,7 @@ def write_qmod(
|
|
22
23
|
The native Qmod file may be uploaded to the Classiq IDE.
|
23
24
|
|
24
25
|
Args:
|
25
|
-
|
26
|
+
model: The entry point of the Qmod model - a qfunc named 'main' (or alternatively the output of 'create_model').
|
26
27
|
name: The name to save the file by.
|
27
28
|
directory: The directory to save the files in. If None, the current working directory is used.
|
28
29
|
decimal_precision: The number of decimal places to use for numbers, set to 4 by default.
|
@@ -30,13 +31,15 @@ def write_qmod(
|
|
30
31
|
Returns:
|
31
32
|
None
|
32
33
|
"""
|
33
|
-
|
34
|
-
|
34
|
+
if isinstance(model, (QFunc, GenerativeQFunc)):
|
35
|
+
model_obj = model.create_model()
|
36
|
+
else:
|
37
|
+
model_obj = Model.model_validate_json(model)
|
35
38
|
pretty_printed_model = DSLPrettyPrinter(decimal_precision=decimal_precision).visit(
|
36
|
-
|
39
|
+
model_obj
|
37
40
|
)
|
38
41
|
|
39
|
-
synthesis_options =
|
42
|
+
synthesis_options = model_obj.model_dump(
|
40
43
|
include={"constraints", "preferences"}, exclude_none=True
|
41
44
|
)
|
42
45
|
|
classiq/synthesis.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any, NewType, Optional
|
1
|
+
from typing import Any, NewType, Optional, Union
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
|
@@ -12,6 +12,8 @@ from classiq.interface.model.model import Model, SerializedModel
|
|
12
12
|
from classiq import QuantumProgram
|
13
13
|
from classiq._internals import async_utils
|
14
14
|
from classiq._internals.api_wrapper import ApiWrapper
|
15
|
+
from classiq.qmod.create_model_function import create_model
|
16
|
+
from classiq.qmod.quantum_function import GenerativeQFunc, QFunc
|
15
17
|
|
16
18
|
SerializedQuantumProgram = NewType("SerializedQuantumProgram", str)
|
17
19
|
|
@@ -69,19 +71,30 @@ async def synthesize_async(
|
|
69
71
|
|
70
72
|
|
71
73
|
def synthesize(
|
72
|
-
|
74
|
+
model: Union[SerializedModel, QFunc, GenerativeQFunc],
|
75
|
+
auto_show: bool = False,
|
76
|
+
constraints: Optional[Constraints] = None,
|
77
|
+
preferences: Optional[Preferences] = None,
|
73
78
|
) -> SerializedQuantumProgram:
|
74
79
|
"""
|
75
80
|
Synthesize a model with the Classiq engine to receive a quantum program.
|
76
81
|
[More details](https://docs.classiq.io/latest/reference-manual/synthesis/)
|
77
82
|
|
78
83
|
Args:
|
79
|
-
|
80
|
-
auto_show:
|
84
|
+
model: The entry point of the Qmod model - a qfunc named 'main' (or alternatively the output of 'create_model').
|
85
|
+
auto_show: Whether to 'show' the synthesized model (False by default).
|
86
|
+
constraints: Constraints for the synthesis of the model. See Constraints (Optional).
|
87
|
+
preferences: Preferences for the synthesis of the model. See Preferences (Optional).
|
81
88
|
|
82
89
|
Returns:
|
83
90
|
SerializedQuantumProgram: Quantum program serialized as a string. (See: QuantumProgram)
|
84
91
|
"""
|
92
|
+
if isinstance(model, (QFunc, GenerativeQFunc)):
|
93
|
+
serialized_model = create_model(
|
94
|
+
model, constraints=constraints, preferences=preferences
|
95
|
+
)
|
96
|
+
else:
|
97
|
+
serialized_model = model
|
85
98
|
result = async_utils.run(synthesize_async(serialized_model))
|
86
99
|
if auto_show:
|
87
100
|
show(result)
|
@@ -91,7 +104,7 @@ def synthesize(
|
|
91
104
|
def set_preferences(
|
92
105
|
serialized_model: SerializedModel,
|
93
106
|
preferences: Optional[Preferences] = None,
|
94
|
-
**kwargs: Any
|
107
|
+
**kwargs: Any,
|
95
108
|
) -> SerializedModel:
|
96
109
|
"""
|
97
110
|
Overrides the preferences of a (serialized) model and returns the updated model.
|
@@ -139,7 +152,7 @@ def update_preferences(
|
|
139
152
|
def set_constraints(
|
140
153
|
serialized_model: SerializedModel,
|
141
154
|
constraints: Optional[Constraints] = None,
|
142
|
-
**kwargs: Any
|
155
|
+
**kwargs: Any,
|
143
156
|
) -> SerializedModel:
|
144
157
|
"""
|
145
158
|
Overrides the constraints of a (serialized) model and returns the updated model.
|
@@ -187,7 +200,7 @@ def update_constraints(
|
|
187
200
|
def set_execution_preferences(
|
188
201
|
serialized_model: SerializedModel,
|
189
202
|
execution_preferences: Optional[ExecutionPreferences] = None,
|
190
|
-
**kwargs: Any
|
203
|
+
**kwargs: Any,
|
191
204
|
) -> SerializedModel:
|
192
205
|
"""
|
193
206
|
Overrides the execution preferences of a (serialized) model and returns the updated model.
|