classiq 0.76.0__py3-none-any.whl → 0.78.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/applications/chemistry/chemistry_model_constructor.py +7 -6
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +9 -1
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -3
- classiq/applications/iqae/__init__.py +0 -0
- classiq/applications/iqae/iqae.py +207 -0
- classiq/execution/__init__.py +1 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/applications/iqae/__init__.py +0 -0
- classiq/interface/applications/iqae/generic_iqae.py +222 -0
- classiq/interface/applications/iqae/iqae_result.py +45 -0
- classiq/interface/debug_info/debug_info.py +3 -0
- classiq/interface/executor/execution_result.py +1 -1
- classiq/interface/executor/user_budget.py +1 -1
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +9 -3
- classiq/interface/generator/expressions/proxies/quantum/qmod_qarray_proxy.py +6 -15
- classiq/interface/generator/expressions/proxies/quantum/qmod_qscalar_proxy.py +14 -5
- classiq/interface/generator/expressions/proxies/quantum/qmod_sized_proxy.py +5 -3
- classiq/interface/generator/generated_circuit_data.py +18 -7
- classiq/interface/ide/visual_model.py +2 -0
- classiq/interface/model/handle_binding.py +8 -0
- classiq/interface/model/model.py +3 -6
- classiq/interface/model/quantum_function_call.py +31 -1
- classiq/interface/model/quantum_statement.py +14 -1
- classiq/interface/source_reference.py +7 -2
- classiq/model_expansions/capturing/captured_vars.py +16 -6
- classiq/model_expansions/closure.py +1 -58
- classiq/model_expansions/evaluators/arg_type_match.py +2 -2
- classiq/model_expansions/evaluators/argument_types.py +4 -5
- classiq/model_expansions/evaluators/classical_expression.py +9 -9
- classiq/model_expansions/evaluators/parameter_types.py +19 -11
- classiq/model_expansions/expression_evaluator.py +20 -11
- classiq/model_expansions/generative_functions.py +1 -1
- classiq/model_expansions/interpreters/base_interpreter.py +27 -15
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +0 -16
- classiq/model_expansions/interpreters/generative_interpreter.py +4 -4
- classiq/model_expansions/quantum_operations/allocate.py +2 -2
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +3 -1
- classiq/model_expansions/quantum_operations/call_emitter.py +91 -42
- classiq/model_expansions/quantum_operations/emitter.py +7 -7
- classiq/model_expansions/quantum_operations/function_calls_cache.py +84 -0
- classiq/model_expansions/scope.py +73 -13
- classiq/model_expansions/transformers/model_renamer.py +2 -2
- classiq/model_expansions/transformers/type_qualifier_inference.py +183 -0
- classiq/model_expansions/utils/text_utils.py +4 -2
- classiq/model_expansions/visitors/symbolic_param_inference.py +4 -15
- classiq/open_library/functions/lookup_table.py +1 -1
- classiq/open_library/functions/state_preparation.py +1 -1
- classiq/qmod/builtins/classical_execution_primitives.py +1 -1
- classiq/qmod/create_model_function.py +21 -3
- classiq/qmod/global_declarative_switch.py +19 -0
- classiq/qmod/native/pretty_printer.py +4 -0
- classiq/qmod/pretty_print/pretty_printer.py +4 -0
- classiq/qmod/qfunc.py +31 -23
- classiq/qmod/qmod_variable.py +7 -4
- classiq/qmod/quantum_expandable.py +29 -1
- classiq/qmod/quantum_function.py +26 -19
- classiq/qmod/utilities.py +4 -0
- classiq/qmod/write_qmod.py +36 -10
- classiq/synthesis.py +7 -6
- {classiq-0.76.0.dist-info → classiq-0.78.0.dist-info}/METADATA +1 -1
- {classiq-0.76.0.dist-info → classiq-0.78.0.dist-info}/RECORD +62 -55
- classiq/interface/executor/iqae_result.py +0 -17
- {classiq-0.76.0.dist-info → classiq-0.78.0.dist-info}/WHEEL +0 -0
classiq/qmod/qfunc.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
|
2
|
-
from contextlib import contextmanager
|
1
|
+
import warnings
|
3
2
|
from typing import Callable, Literal, Optional, Union, overload
|
4
3
|
|
5
|
-
from classiq.interface.exceptions import ClassiqInternalError
|
4
|
+
from classiq.interface.exceptions import ClassiqDeprecationWarning, ClassiqInternalError
|
6
5
|
|
6
|
+
from classiq.qmod.global_declarative_switch import get_global_declarative_switch
|
7
7
|
from classiq.qmod.quantum_callable import QCallable
|
8
8
|
from classiq.qmod.quantum_function import (
|
9
9
|
BaseQFunc,
|
@@ -12,22 +12,9 @@ from classiq.qmod.quantum_function import (
|
|
12
12
|
QFunc,
|
13
13
|
)
|
14
14
|
|
15
|
-
_GENERATIVE_SWITCH = False
|
16
|
-
|
17
|
-
|
18
|
-
@contextmanager
|
19
|
-
def set_global_generative_switch() -> Iterator[None]:
|
20
|
-
global _GENERATIVE_SWITCH
|
21
|
-
previous = _GENERATIVE_SWITCH
|
22
|
-
_GENERATIVE_SWITCH = True
|
23
|
-
try:
|
24
|
-
yield
|
25
|
-
finally:
|
26
|
-
_GENERATIVE_SWITCH = previous
|
27
|
-
|
28
15
|
|
29
16
|
@overload
|
30
|
-
def qfunc(func: Callable) ->
|
17
|
+
def qfunc(func: Callable) -> GenerativeQFunc: ...
|
31
18
|
|
32
19
|
|
33
20
|
@overload
|
@@ -42,16 +29,16 @@ def qfunc(
|
|
42
29
|
@overload
|
43
30
|
def qfunc(
|
44
31
|
*,
|
45
|
-
generative: Literal[
|
32
|
+
generative: Literal[False],
|
46
33
|
synthesize_separately: bool = False,
|
47
34
|
atomic_qualifiers: Optional[list[str]] = None,
|
48
|
-
) -> Callable[[Callable],
|
35
|
+
) -> Callable[[Callable], QFunc]: ...
|
49
36
|
|
50
37
|
|
51
38
|
@overload
|
52
39
|
def qfunc(
|
53
40
|
*, synthesize_separately: bool, atomic_qualifiers: Optional[list[str]] = None
|
54
|
-
) -> Callable[[Callable],
|
41
|
+
) -> Callable[[Callable], GenerativeQFunc]: ...
|
55
42
|
|
56
43
|
|
57
44
|
@overload
|
@@ -59,17 +46,38 @@ def qfunc(
|
|
59
46
|
*,
|
60
47
|
synthesize_separately: bool = False,
|
61
48
|
atomic_qualifiers: Optional[list[str]] = None,
|
62
|
-
) -> Callable[[Callable],
|
49
|
+
) -> Callable[[Callable], GenerativeQFunc]: ...
|
63
50
|
|
64
51
|
|
65
52
|
def qfunc(
|
66
53
|
func: Optional[Callable] = None,
|
67
54
|
*,
|
68
55
|
external: bool = False,
|
69
|
-
generative: bool =
|
56
|
+
generative: Optional[bool] = None,
|
70
57
|
synthesize_separately: bool = False,
|
71
58
|
atomic_qualifiers: Optional[list[str]] = None,
|
72
59
|
) -> Union[Callable[[Callable], QCallable], QCallable]:
|
60
|
+
if generative is True:
|
61
|
+
warnings.warn(
|
62
|
+
"The use of `generative=True` is no longer required. Note that the "
|
63
|
+
"treatment of parameters of Qmod types will change from Python value to "
|
64
|
+
"symbolic in a near release. Change Qmod types to the corresponding Python "
|
65
|
+
"built-in types in order to use the parameters in Python expression "
|
66
|
+
"contexts.\n"
|
67
|
+
"Recommended changes:\n"
|
68
|
+
"@qfunc(generative=True) -> @qfunc\n"
|
69
|
+
"CInt->int\n"
|
70
|
+
"CReal->float\n"
|
71
|
+
"CArray->list\n\n"
|
72
|
+
"For more information see https://docs.classiq.io/latest/qmod-reference/language-reference/generative-descriptions/",
|
73
|
+
ClassiqDeprecationWarning,
|
74
|
+
stacklevel=2,
|
75
|
+
)
|
76
|
+
elif generative is None:
|
77
|
+
generative = True
|
78
|
+
if get_global_declarative_switch():
|
79
|
+
generative = False
|
80
|
+
|
73
81
|
def wrapper(func: Callable) -> QCallable:
|
74
82
|
qfunc: BaseQFunc
|
75
83
|
|
@@ -77,7 +85,7 @@ def qfunc(
|
|
77
85
|
_validate_directives(synthesize_separately, atomic_qualifiers)
|
78
86
|
return ExternalQFunc(func)
|
79
87
|
|
80
|
-
if generative
|
88
|
+
if generative:
|
81
89
|
qfunc = GenerativeQFunc(func)
|
82
90
|
else:
|
83
91
|
qfunc = QFunc(func)
|
classiq/qmod/qmod_variable.py
CHANGED
@@ -103,6 +103,9 @@ def _infer_variable_name(name: Any, depth: int) -> Any:
|
|
103
103
|
return name
|
104
104
|
|
105
105
|
|
106
|
+
_SYMBOLIC_TYPES = tuple(get_origin(t) or t for t in get_args(SymbolicTypes))
|
107
|
+
|
108
|
+
|
106
109
|
class QVar(Symbolic):
|
107
110
|
CONSTRUCTOR_DEPTH: int = 1
|
108
111
|
|
@@ -218,7 +221,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
218
221
|
)
|
219
222
|
|
220
223
|
def __ior__(self, other: Any) -> Self:
|
221
|
-
if not isinstance(other,
|
224
|
+
if not isinstance(other, _SYMBOLIC_TYPES):
|
222
225
|
raise TypeError(
|
223
226
|
f"Invalid argument {other!r} for out-of-place arithmetic operation"
|
224
227
|
)
|
@@ -229,7 +232,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
229
232
|
return self
|
230
233
|
|
231
234
|
def __ixor__(self, other: Any) -> Self:
|
232
|
-
if not isinstance(other,
|
235
|
+
if not isinstance(other, _SYMBOLIC_TYPES):
|
233
236
|
raise TypeError(
|
234
237
|
f"Invalid argument {other!r} for in-place arithmetic operation"
|
235
238
|
)
|
@@ -240,7 +243,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
240
243
|
return self
|
241
244
|
|
242
245
|
def __iadd__(self, other: Any) -> Self:
|
243
|
-
if not isinstance(other,
|
246
|
+
if not isinstance(other, _SYMBOLIC_TYPES):
|
244
247
|
raise TypeError(
|
245
248
|
f"Invalid argument {other!r} for in-place arithmetic operation"
|
246
249
|
)
|
@@ -251,7 +254,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
251
254
|
return self
|
252
255
|
|
253
256
|
def __imul__(self, other: Any) -> Self:
|
254
|
-
if not isinstance(other,
|
257
|
+
if not isinstance(other, _SYMBOLIC_TYPES):
|
255
258
|
raise TypeError(
|
256
259
|
f"Invalid argument {other!r} for out of ampltiude encoding operation"
|
257
260
|
)
|
@@ -28,6 +28,7 @@ from classiq.interface.generator.functions.concrete_types import (
|
|
28
28
|
from classiq.interface.model.classical_parameter_declaration import (
|
29
29
|
AnonClassicalParameterDeclaration,
|
30
30
|
)
|
31
|
+
from classiq.interface.model.handle_binding import GeneralHandle, HandlesList
|
31
32
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
32
33
|
from classiq.interface.model.quantum_function_call import (
|
33
34
|
ArgValue,
|
@@ -52,6 +53,7 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
52
53
|
from classiq.interface.source_reference import SourceReference
|
53
54
|
|
54
55
|
from classiq.qmod.generative import generative_mode_context, is_generative_mode
|
56
|
+
from classiq.qmod.global_declarative_switch import get_global_declarative_switch
|
55
57
|
from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
|
56
58
|
from classiq.qmod.qmod_constant import QConstant
|
57
59
|
from classiq.qmod.qmod_parameter import (
|
@@ -84,6 +86,11 @@ class QExpandable(QCallable, QExpandableInterface, ABC):
|
|
84
86
|
self._py_callable: Callable = py_callable
|
85
87
|
self._body: list[QuantumStatement] = list()
|
86
88
|
|
89
|
+
def __eq__(self, other: Any) -> bool:
|
90
|
+
return (
|
91
|
+
isinstance(other, QExpandable) and self._py_callable is other._py_callable
|
92
|
+
)
|
93
|
+
|
87
94
|
@property
|
88
95
|
def body(self) -> list[QuantumStatement]:
|
89
96
|
return self._body
|
@@ -317,8 +324,10 @@ def prepare_arg(
|
|
317
324
|
def prepare_arg(
|
318
325
|
arg_decl: AnonPositionalArg, val: Any, func_name: Optional[str], param_name: str
|
319
326
|
) -> ArgValue:
|
320
|
-
from classiq.qmod.quantum_function import BaseQFunc, GenerativeQFunc
|
327
|
+
from classiq.qmod.quantum_function import BaseQFunc, GenerativeQFunc, QFunc
|
321
328
|
|
329
|
+
if get_global_declarative_switch() and isinstance(val, GenerativeQFunc):
|
330
|
+
val = QFunc(val._py_callable)
|
322
331
|
if isinstance(val, BaseQFunc):
|
323
332
|
val.add_function_dependencies()
|
324
333
|
if isinstance(val, GenerativeQFunc):
|
@@ -330,6 +339,9 @@ def prepare_arg(
|
|
330
339
|
_validate_classical_arg(val, arg_decl, func_name)
|
331
340
|
return Expression(expr=qmod_val_to_expr_str(val))
|
332
341
|
elif isinstance(arg_decl, AnonPortDeclaration):
|
342
|
+
handles_list = _try_preparing_handles_list(val)
|
343
|
+
if handles_list is not None:
|
344
|
+
return handles_list
|
333
345
|
if not isinstance(val, QVar):
|
334
346
|
func_name_message = (
|
335
347
|
"" if func_name is None else f" of function {func_name!r}"
|
@@ -505,3 +517,19 @@ def _is_legal_iterable_element(arg: Any) -> bool:
|
|
505
517
|
if isinstance(arg, Iterable):
|
506
518
|
return all(_is_legal_iterable_element(e) for e in arg)
|
507
519
|
return True
|
520
|
+
|
521
|
+
|
522
|
+
def _try_preparing_handles_list(val: Any) -> Optional[HandlesList]:
|
523
|
+
if not isinstance(val, list):
|
524
|
+
return None
|
525
|
+
items = [
|
526
|
+
(
|
527
|
+
item.get_handle_binding()
|
528
|
+
if isinstance(item, QVar)
|
529
|
+
else _try_preparing_handles_list(item)
|
530
|
+
)
|
531
|
+
for item in val
|
532
|
+
]
|
533
|
+
if any(item is None for item in items):
|
534
|
+
return None
|
535
|
+
return HandlesList(handles=cast(list[GeneralHandle], items))
|
classiq/qmod/quantum_function.py
CHANGED
@@ -26,6 +26,7 @@ from classiq.qmod.classical_function import CFunc
|
|
26
26
|
from classiq.qmod.cparam import CParamAbstract
|
27
27
|
from classiq.qmod.declaration_inferrer import infer_func_decl, is_qvar
|
28
28
|
from classiq.qmod.generative import set_frontend_interpreter
|
29
|
+
from classiq.qmod.global_declarative_switch import get_global_declarative_switch
|
29
30
|
from classiq.qmod.qmod_constant import QConstant
|
30
31
|
from classiq.qmod.qmod_parameter import CArray
|
31
32
|
from classiq.qmod.quantum_callable import QCallable, QCallableList
|
@@ -49,6 +50,18 @@ class BaseQFunc(QExpandable):
|
|
49
50
|
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
50
51
|
raise NotImplementedError
|
51
52
|
|
53
|
+
@property
|
54
|
+
def pure_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
55
|
+
if type(self.func_decl) is NamedParamsQuantumFunctionDeclaration:
|
56
|
+
return self.func_decl
|
57
|
+
return NamedParamsQuantumFunctionDeclaration(
|
58
|
+
**{
|
59
|
+
k: v
|
60
|
+
for k, v in self.func_decl.model_dump().items()
|
61
|
+
if k in NamedParamsQuantumFunctionDeclaration.model_fields
|
62
|
+
}
|
63
|
+
)
|
64
|
+
|
52
65
|
@property
|
53
66
|
def _has_inputs(self) -> bool:
|
54
67
|
return any(
|
@@ -90,18 +103,6 @@ class QFunc(BaseQFunc):
|
|
90
103
|
super().__init__(py_callable, compilation_metadata)
|
91
104
|
self.compilation_metadata: Optional[CompilationMetadata] = None
|
92
105
|
|
93
|
-
@property
|
94
|
-
def pure_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
95
|
-
if type(self.func_decl) is NamedParamsQuantumFunctionDeclaration:
|
96
|
-
return self.func_decl
|
97
|
-
return NamedParamsQuantumFunctionDeclaration(
|
98
|
-
**{
|
99
|
-
k: v
|
100
|
-
for k, v in self.func_decl.model_dump().items()
|
101
|
-
if k in NamedParamsQuantumFunctionDeclaration.model_fields
|
102
|
-
}
|
103
|
-
)
|
104
|
-
|
105
106
|
@property
|
106
107
|
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
107
108
|
name = self._py_callable.__name__
|
@@ -142,7 +143,10 @@ class QFunc(BaseQFunc):
|
|
142
143
|
functions_compilation_metadata=self._qmodule.functions_compilation_metadata,
|
143
144
|
**{key: value for key, value in model_extra_settings if value},
|
144
145
|
)
|
145
|
-
if
|
146
|
+
if (
|
147
|
+
not get_global_declarative_switch()
|
148
|
+
and len(self._qmodule.generative_functions) > 0
|
149
|
+
):
|
146
150
|
return self._create_generative_model(model)
|
147
151
|
return model
|
148
152
|
|
@@ -233,12 +237,6 @@ class ExternalQFunc(QTerminalCallable):
|
|
233
237
|
def pure_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
234
238
|
return self.func_decl
|
235
239
|
|
236
|
-
def get_implementation(self) -> NativeFunctionDefinition:
|
237
|
-
model = QFunc(self._py_callable).create_model()
|
238
|
-
return [
|
239
|
-
func for func in model.functions if func.name == self._py_callable.__name__
|
240
|
-
][0]
|
241
|
-
|
242
240
|
|
243
241
|
class GenerativeQFunc(BaseQFunc):
|
244
242
|
FRAME_DEPTH = 3
|
@@ -262,6 +260,8 @@ class GenerativeQFunc(BaseQFunc):
|
|
262
260
|
return self._inferred_func_decl
|
263
261
|
|
264
262
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
263
|
+
if get_global_declarative_switch():
|
264
|
+
return QFunc(self._py_callable)(*args, **kwargs)
|
265
265
|
if self.func_decl.name not in self._qmodule.generative_functions:
|
266
266
|
self._qmodule.generative_functions[self.func_decl.name] = self
|
267
267
|
if self._func_decl is None:
|
@@ -277,6 +277,13 @@ class GenerativeQFunc(BaseQFunc):
|
|
277
277
|
preferences: Optional[Preferences] = None,
|
278
278
|
classical_execution_function: Optional[CFunc] = None,
|
279
279
|
) -> Model:
|
280
|
+
if get_global_declarative_switch():
|
281
|
+
return QFunc(self._py_callable).create_model(
|
282
|
+
constraints,
|
283
|
+
execution_preferences,
|
284
|
+
preferences,
|
285
|
+
classical_execution_function,
|
286
|
+
)
|
280
287
|
self._qmodule.reset()
|
281
288
|
if self.func_decl.name == MAIN_FUNCTION_NAME:
|
282
289
|
validate_main_function(self.func_decl)
|
classiq/qmod/utilities.py
CHANGED
@@ -20,6 +20,7 @@ from typing import (
|
|
20
20
|
overload,
|
21
21
|
)
|
22
22
|
|
23
|
+
import sympy
|
23
24
|
from typing_extensions import ParamSpec
|
24
25
|
|
25
26
|
from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
|
@@ -101,6 +102,9 @@ def get_source_ref(frame: FrameType) -> SourceReference:
|
|
101
102
|
|
102
103
|
|
103
104
|
def qmod_val_to_expr_str(val: Any) -> str:
|
105
|
+
if isinstance(val, sympy.Basic):
|
106
|
+
return str(val)
|
107
|
+
|
104
108
|
if dataclasses.is_dataclass(type(val)):
|
105
109
|
kwargs_str = ", ".join(
|
106
110
|
[
|
classiq/qmod/write_qmod.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
import json
|
2
2
|
from pathlib import Path
|
3
|
-
from typing import
|
3
|
+
from typing import Optional, Union
|
4
4
|
|
5
5
|
from classiq.interface.model.model import Model, SerializedModel
|
6
6
|
|
7
|
+
from classiq.qmod.global_declarative_switch import set_global_declarative_switch
|
7
8
|
from classiq.qmod.native.pretty_printer import DSLPrettyPrinter
|
8
9
|
from classiq.qmod.quantum_function import GenerativeQFunc, QFunc
|
9
10
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
@@ -17,8 +18,7 @@ def write_qmod(
|
|
17
18
|
name: str,
|
18
19
|
directory: Optional[Path] = None,
|
19
20
|
decimal_precision: int = DEFAULT_DECIMAL_PRECISION,
|
20
|
-
|
21
|
-
**kwargs: Any,
|
21
|
+
symbolic_only: bool = True,
|
22
22
|
) -> None:
|
23
23
|
"""
|
24
24
|
Creates a native Qmod file from a serialized model and outputs the synthesis options (Preferences and Constraints) to a file.
|
@@ -29,20 +29,15 @@ def write_qmod(
|
|
29
29
|
name: The name to save the file by.
|
30
30
|
directory: The directory to save the files in. If None, the current working directory is used.
|
31
31
|
decimal_precision: The number of decimal places to use for numbers, set to 4 by default.
|
32
|
-
|
33
|
-
kwargs: (placeholder)
|
32
|
+
symbolic_only: If True keep function definitions un-expanded and symbolic (note that Qmod functions with parameters of Python types are not supported in this mode)
|
34
33
|
|
35
34
|
Returns:
|
36
35
|
None
|
37
36
|
"""
|
38
|
-
|
39
|
-
model_obj = model.create_model()
|
40
|
-
else:
|
41
|
-
model_obj = Model.model_validate_json(model)
|
37
|
+
model_obj = prepare_write_qmod_model(model, symbolic_only)
|
42
38
|
pretty_printed_model = DSLPrettyPrinter(decimal_precision=decimal_precision).visit(
|
43
39
|
model_obj
|
44
40
|
)
|
45
|
-
|
46
41
|
synthesis_options = model_obj.model_dump(
|
47
42
|
include={"constraints", "preferences"}, exclude_none=True
|
48
43
|
)
|
@@ -58,3 +53,34 @@ def write_qmod(
|
|
58
53
|
native_qmod_path = directory / native_qmod_path
|
59
54
|
|
60
55
|
native_qmod_path.write_text(pretty_printed_model)
|
56
|
+
|
57
|
+
|
58
|
+
def prepare_write_qmod_model(
|
59
|
+
model: Union[SerializedModel, QFunc, GenerativeQFunc], symbolic_only: bool
|
60
|
+
) -> Model:
|
61
|
+
if isinstance(model, str) and hasattr(model, "entry_point") and symbolic_only:
|
62
|
+
model_obj = Model.model_validate_json(model)
|
63
|
+
with set_global_declarative_switch():
|
64
|
+
dec_model_obj = model.entry_point.create_model(
|
65
|
+
constraints=model_obj.constraints,
|
66
|
+
execution_preferences=model_obj.execution_preferences,
|
67
|
+
preferences=model_obj.preferences,
|
68
|
+
)
|
69
|
+
dec_constant_names = {const.name for const in dec_model_obj.constants}
|
70
|
+
all_constants = dec_model_obj.constants + [
|
71
|
+
const
|
72
|
+
for const in model_obj.constants
|
73
|
+
if const.name not in dec_constant_names
|
74
|
+
]
|
75
|
+
return dec_model_obj.model_copy(
|
76
|
+
update={
|
77
|
+
"constants": all_constants,
|
78
|
+
"classical_execution_code": model_obj.classical_execution_code,
|
79
|
+
}
|
80
|
+
)
|
81
|
+
if isinstance(model, (QFunc, GenerativeQFunc)):
|
82
|
+
if symbolic_only:
|
83
|
+
with set_global_declarative_switch():
|
84
|
+
return model.create_model()
|
85
|
+
return model.create_model()
|
86
|
+
return Model.model_validate_json(model)
|
classiq/synthesis.py
CHANGED
@@ -10,6 +10,7 @@ from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model, SerializedM
|
|
10
10
|
from classiq import QuantumProgram
|
11
11
|
from classiq._internals import async_utils
|
12
12
|
from classiq._internals.api_wrapper import ApiWrapper
|
13
|
+
from classiq.qmod.create_model_function import add_entry_point
|
13
14
|
from classiq.qmod.quantum_function import BaseQFunc
|
14
15
|
|
15
16
|
SerializedQuantumProgram = QuantumProgram
|
@@ -116,7 +117,7 @@ def set_preferences(
|
|
116
117
|
|
117
118
|
model = Model.model_validate_json(serialized_model)
|
118
119
|
model.preferences = preferences
|
119
|
-
return model.get_model()
|
120
|
+
return add_entry_point(model.get_model(), serialized_model)
|
120
121
|
|
121
122
|
|
122
123
|
def update_preferences(
|
@@ -136,7 +137,7 @@ def update_preferences(
|
|
136
137
|
|
137
138
|
for key, value in kwargs.items():
|
138
139
|
setattr(model.preferences, key, value)
|
139
|
-
return model.get_model()
|
140
|
+
return add_entry_point(model.get_model(), serialized_model)
|
140
141
|
|
141
142
|
|
142
143
|
def set_constraints(
|
@@ -164,7 +165,7 @@ def set_constraints(
|
|
164
165
|
|
165
166
|
model = Model.model_validate_json(serialized_model)
|
166
167
|
model.constraints = constraints
|
167
|
-
return model.get_model()
|
168
|
+
return add_entry_point(model.get_model(), serialized_model)
|
168
169
|
|
169
170
|
|
170
171
|
def update_constraints(
|
@@ -184,7 +185,7 @@ def update_constraints(
|
|
184
185
|
|
185
186
|
for key, value in kwargs.items():
|
186
187
|
setattr(model.constraints, key, value)
|
187
|
-
return model.get_model()
|
188
|
+
return add_entry_point(model.get_model(), serialized_model)
|
188
189
|
|
189
190
|
|
190
191
|
def set_execution_preferences(
|
@@ -213,7 +214,7 @@ def set_execution_preferences(
|
|
213
214
|
|
214
215
|
model = Model.model_validate_json(serialized_model)
|
215
216
|
model.execution_preferences = execution_preferences
|
216
|
-
return model.get_model()
|
217
|
+
return add_entry_point(model.get_model(), serialized_model)
|
217
218
|
|
218
219
|
|
219
220
|
def update_execution_preferences(
|
@@ -234,7 +235,7 @@ def update_execution_preferences(
|
|
234
235
|
for key, value in kwargs.items():
|
235
236
|
setattr(model.execution_preferences, key, value)
|
236
237
|
|
237
|
-
return model.get_model()
|
238
|
+
return add_entry_point(model.get_model(), serialized_model)
|
238
239
|
|
239
240
|
|
240
241
|
__all__ = [
|