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.
Files changed (89) hide show
  1. classiq/_internals/api_wrapper.py +5 -1
  2. classiq/_internals/async_utils.py +1 -1
  3. classiq/_internals/authentication/password_manager.py +1 -1
  4. classiq/_internals/client.py +1 -1
  5. classiq/applications/finance/finance_model_constructor.py +9 -0
  6. classiq/applications/grover/grover_model_constructor.py +10 -0
  7. classiq/applications/qnn/qlayer.py +8 -2
  8. classiq/applications/qsvm/qsvm_model_constructor.py +9 -0
  9. classiq/execution/execution_session.py +7 -3
  10. classiq/executor.py +7 -2
  11. classiq/interface/_version.py +1 -1
  12. classiq/interface/ast_node.py +1 -1
  13. classiq/interface/chemistry/operator.py +1 -1
  14. classiq/interface/debug_info/debug_info.py +27 -0
  15. classiq/interface/exceptions.py +2 -5
  16. classiq/interface/generator/arith/argument_utils.py +1 -1
  17. classiq/interface/generator/arith/arithmetic.py +99 -2
  18. classiq/interface/generator/arith/arithmetic_expression_parser.py +1 -1
  19. classiq/interface/generator/arith/binary_ops.py +3 -0
  20. classiq/interface/generator/function_param_list_without_self_reference.py +2 -0
  21. classiq/interface/generator/functions/type_name.py +2 -2
  22. classiq/interface/generator/generated_circuit_data.py +38 -3
  23. classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
  24. classiq/interface/generator/hva.py +1 -1
  25. classiq/interface/generator/model/preferences/preferences.py +8 -1
  26. classiq/interface/generator/quantum_program.py +18 -1
  27. classiq/interface/generator/reset.py +14 -0
  28. classiq/interface/generator/types/enum_declaration.py +33 -2
  29. classiq/interface/generator/ucc.py +1 -1
  30. classiq/interface/interface_version.py +1 -1
  31. classiq/interface/model/classical_if.py +2 -2
  32. classiq/interface/model/control.py +2 -2
  33. classiq/interface/model/invert.py +2 -2
  34. classiq/interface/model/power.py +2 -2
  35. classiq/interface/model/quantum_function_call.py +4 -0
  36. classiq/interface/model/quantum_statement.py +13 -0
  37. classiq/interface/model/repeat.py +2 -2
  38. classiq/interface/model/statement_block.py +1 -1
  39. classiq/interface/model/within_apply_operation.py +2 -2
  40. classiq/model_expansions/atomic_expression_functions_defs.py +2 -1
  41. classiq/model_expansions/capturing/captured_vars.py +184 -54
  42. classiq/model_expansions/closure.py +6 -3
  43. classiq/model_expansions/evaluators/control.py +14 -38
  44. classiq/model_expansions/function_builder.py +19 -14
  45. classiq/model_expansions/generative_functions.py +7 -11
  46. classiq/model_expansions/interpreters/base_interpreter.py +14 -5
  47. classiq/model_expansions/interpreters/generative_interpreter.py +87 -26
  48. classiq/model_expansions/quantum_operations/allocate.py +9 -3
  49. classiq/model_expansions/quantum_operations/assignment_result_processor.py +52 -0
  50. classiq/model_expansions/quantum_operations/bind.py +67 -14
  51. classiq/model_expansions/quantum_operations/block_evaluator.py +76 -0
  52. classiq/model_expansions/quantum_operations/call_emitter.py +79 -10
  53. classiq/model_expansions/quantum_operations/classicalif.py +10 -6
  54. classiq/model_expansions/quantum_operations/composite_emitter.py +27 -0
  55. classiq/model_expansions/quantum_operations/emitter.py +24 -3
  56. classiq/model_expansions/quantum_operations/expression_evaluator.py +33 -0
  57. classiq/model_expansions/quantum_operations/handle_evaluator.py +28 -0
  58. classiq/model_expansions/quantum_operations/quantum_function_call.py +3 -2
  59. classiq/model_expansions/quantum_operations/repeat.py +9 -3
  60. classiq/model_expansions/quantum_operations/variable_decleration.py +13 -2
  61. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +1 -1
  62. classiq/open_library/functions/__init__.py +1 -2
  63. classiq/open_library/functions/amplitude_amplification.py +12 -9
  64. classiq/open_library/functions/discrete_sine_cosine_transform.py +16 -13
  65. classiq/open_library/functions/grover.py +11 -15
  66. classiq/open_library/functions/modular_exponentiation.py +7 -13
  67. classiq/open_library/functions/state_preparation.py +16 -17
  68. classiq/open_library/functions/swap_test.py +1 -1
  69. classiq/open_library/functions/utility_functions.py +10 -2
  70. classiq/qmod/builtins/functions/__init__.py +3 -0
  71. classiq/qmod/builtins/functions/chemistry.py +6 -38
  72. classiq/qmod/builtins/functions/mid_circuit_measurement.py +15 -0
  73. classiq/qmod/quantum_expandable.py +30 -6
  74. classiq/qmod/quantum_function.py +4 -0
  75. classiq/qmod/semantics/annotation/call_annotation.py +8 -2
  76. classiq/qmod/semantics/annotation/model_annotation.py +9 -0
  77. classiq/qmod/semantics/error_manager.py +0 -6
  78. classiq/qmod/semantics/static_semantics_visitor.py +0 -347
  79. classiq/qmod/semantics/validation/types_validation.py +1 -1
  80. classiq/qmod/symbolic.py +2 -1
  81. classiq/qmod/utilities.py +2 -1
  82. classiq/qmod/write_qmod.py +10 -7
  83. classiq/synthesis.py +20 -7
  84. {classiq-0.66.1.dist-info → classiq-0.68.0.dist-info}/METADATA +1 -1
  85. {classiq-0.66.1.dist-info → classiq-0.68.0.dist-info}/RECORD +86 -81
  86. classiq/model_expansions/quantum_operations/shallow_emitter.py +0 -166
  87. classiq/qmod/semantics/validation/func_call_validation.py +0 -99
  88. classiq/qmod/semantics/validation/handle_validation.py +0 -85
  89. {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[list[float], list[CReal], list[CParamScalar], CArray[CReal]],
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, list):
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
 
@@ -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
- serialized_model: SerializedModel,
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
- serialized_model: The serialized model to write as a native Qmod file and synthesis options file.
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
- model = Model.model_validate_json(serialized_model)
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
- model
39
+ model_obj
37
40
  )
38
41
 
39
- synthesis_options = model.model_dump(
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
- serialized_model: SerializedModel, auto_show: bool = False
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
- serialized_model: A model object serialized as a string.
80
- auto_show: boolean. whether to call `show` on the output
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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: classiq
3
- Version: 0.66.1
3
+ Version: 0.68.0
4
4
  Summary: Classiq's Python SDK for quantum computing
5
5
  Home-page: https://classiq.io
6
6
  License: Proprietary