classiq 0.83.0__py3-none-any.whl → 0.85.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 +27 -0
- classiq/applications/chemistry/chemistry_model_constructor.py +0 -2
- classiq/applications/chemistry/hartree_fock.py +68 -0
- classiq/applications/chemistry/mapping.py +85 -0
- classiq/applications/chemistry/op_utils.py +79 -0
- classiq/applications/chemistry/problems.py +195 -0
- classiq/applications/chemistry/ucc.py +109 -0
- classiq/applications/chemistry/z2_symmetries.py +368 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +30 -1
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +20 -42
- classiq/{model_expansions/evaluators → evaluators}/arg_type_match.py +12 -4
- classiq/{model_expansions/evaluators → evaluators}/argument_types.py +1 -1
- classiq/evaluators/classical_expression.py +53 -0
- classiq/{model_expansions/evaluators → evaluators}/classical_type_inference.py +3 -4
- classiq/{model_expansions/evaluators → evaluators}/parameter_types.py +17 -15
- classiq/execution/__init__.py +12 -1
- classiq/execution/execution_session.py +238 -49
- classiq/execution/jobs.py +26 -1
- classiq/execution/qnn.py +2 -2
- classiq/execution/user_budgets.py +39 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/constants.py +1 -0
- classiq/interface/debug_info/debug_info.py +0 -4
- classiq/interface/execution/primitives.py +29 -1
- classiq/interface/executor/estimate_cost.py +35 -0
- classiq/interface/executor/execution_result.py +13 -0
- classiq/interface/executor/result.py +116 -1
- classiq/interface/executor/user_budget.py +26 -33
- classiq/interface/generator/expressions/atomic_expression_functions.py +10 -1
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -6
- classiq/interface/generator/functions/builtins/internal_operators.py +2 -0
- classiq/interface/generator/functions/classical_type.py +2 -35
- classiq/interface/generator/functions/concrete_types.py +20 -3
- classiq/interface/generator/functions/type_modifier.py +0 -19
- classiq/interface/generator/generated_circuit_data.py +5 -18
- classiq/interface/generator/types/compilation_metadata.py +0 -3
- classiq/interface/ide/operation_registry.py +45 -0
- classiq/interface/ide/visual_model.py +68 -3
- classiq/interface/model/bounds.py +12 -2
- classiq/interface/model/model.py +12 -7
- classiq/interface/model/port_declaration.py +2 -24
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +7 -4
- classiq/interface/model/variable_declaration_statement.py +33 -6
- classiq/interface/pretty_print/__init__.py +0 -0
- classiq/{qmod/native → interface/pretty_print}/expression_to_qmod.py +18 -11
- classiq/interface/server/routes.py +4 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +47 -6
- classiq/model_expansions/function_builder.py +4 -1
- classiq/model_expansions/interpreters/base_interpreter.py +3 -3
- classiq/model_expansions/interpreters/generative_interpreter.py +16 -1
- classiq/model_expansions/quantum_operations/allocate.py +1 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +64 -22
- classiq/model_expansions/quantum_operations/bind.py +2 -2
- classiq/model_expansions/quantum_operations/bounds.py +7 -1
- classiq/model_expansions/quantum_operations/call_emitter.py +26 -20
- classiq/model_expansions/quantum_operations/classical_var_emitter.py +16 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +31 -11
- classiq/model_expansions/scope.py +7 -0
- classiq/model_expansions/scope_initialization.py +3 -3
- classiq/model_expansions/transformers/model_renamer.py +6 -4
- classiq/model_expansions/transformers/type_modifier_inference.py +81 -43
- classiq/model_expansions/transformers/var_splitter.py +1 -1
- classiq/model_expansions/visitors/symbolic_param_inference.py +2 -3
- classiq/open_library/functions/__init__.py +3 -2
- classiq/open_library/functions/amplitude_amplification.py +10 -18
- classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
- classiq/open_library/functions/grover.py +14 -6
- classiq/open_library/functions/modular_exponentiation.py +22 -20
- classiq/open_library/functions/qaoa_penalty.py +8 -1
- classiq/open_library/functions/state_preparation.py +18 -32
- classiq/qmod/__init__.py +2 -0
- classiq/qmod/builtins/enums.py +23 -0
- classiq/qmod/builtins/functions/__init__.py +2 -0
- classiq/qmod/builtins/functions/exponentiation.py +32 -4
- classiq/qmod/builtins/operations.py +65 -1
- classiq/qmod/builtins/structs.py +55 -3
- classiq/qmod/classical_variable.py +74 -0
- classiq/qmod/declaration_inferrer.py +3 -2
- classiq/qmod/native/pretty_printer.py +20 -20
- classiq/qmod/pretty_print/expression_to_python.py +2 -1
- classiq/qmod/pretty_print/pretty_printer.py +35 -21
- classiq/qmod/python_classical_type.py +12 -5
- classiq/qmod/qfunc.py +2 -19
- classiq/qmod/qmod_constant.py +2 -5
- classiq/qmod/qmod_parameter.py +2 -5
- classiq/qmod/qmod_variable.py +61 -23
- classiq/qmod/quantum_expandable.py +5 -3
- classiq/qmod/quantum_function.py +49 -4
- classiq/qmod/semantics/annotation/qstruct_annotator.py +1 -1
- classiq/qmod/semantics/validation/main_validation.py +1 -9
- classiq/qmod/symbolic_type.py +2 -1
- classiq/qmod/utilities.py +0 -2
- classiq/qmod/write_qmod.py +1 -1
- {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/METADATA +4 -1
- {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/RECORD +101 -90
- classiq/interface/model/quantum_variable_declaration.py +0 -7
- classiq/model_expansions/evaluators/classical_expression.py +0 -36
- /classiq/{model_expansions/evaluators → evaluators}/__init__.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/control.py +0 -0
- /classiq/{model_expansions → evaluators}/expression_evaluator.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/quantum_type_utils.py +0 -0
- /classiq/{model_expansions/evaluators → evaluators}/type_type_match.py +0 -0
- {classiq-0.83.0.dist-info → classiq-0.85.0.dist-info}/WHEEL +0 -0
@@ -31,7 +31,9 @@ CARRAY_ERROR_MESSAGE = (
|
|
31
31
|
|
32
32
|
|
33
33
|
class PythonClassicalType:
|
34
|
-
def convert(
|
34
|
+
def convert(
|
35
|
+
self, py_type: type, nested: bool = False
|
36
|
+
) -> Optional[ConcreteClassicalType]:
|
35
37
|
if py_type is int:
|
36
38
|
return Integer().set_generative()
|
37
39
|
elif py_type is CInt:
|
@@ -45,16 +47,18 @@ class PythonClassicalType:
|
|
45
47
|
elif py_type is CBool:
|
46
48
|
return Bool()
|
47
49
|
elif get_origin(py_type) is list:
|
48
|
-
element_type = self.convert(get_args(py_type)[0])
|
50
|
+
element_type = self.convert(get_args(py_type)[0], nested=True)
|
49
51
|
if element_type is not None:
|
50
52
|
return ClassicalArray(element_type=element_type).set_generative()
|
51
53
|
elif get_origin(py_type) is CArray:
|
52
54
|
array_args = version_portable_get_args(py_type)
|
53
55
|
if len(array_args) == 1:
|
54
|
-
return ClassicalArray(
|
56
|
+
return ClassicalArray(
|
57
|
+
element_type=self.convert(array_args[0], nested=True)
|
58
|
+
)
|
55
59
|
elif len(array_args) == 2:
|
56
60
|
return ClassicalArray(
|
57
|
-
element_type=self.convert(array_args[0]),
|
61
|
+
element_type=self.convert(array_args[0], nested=True),
|
58
62
|
length=Expression(expr=get_type_hint_expr(array_args[1])),
|
59
63
|
)
|
60
64
|
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
@@ -62,7 +66,10 @@ class PythonClassicalType:
|
|
62
66
|
return self.register_struct(py_type)
|
63
67
|
elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
|
64
68
|
self.register_enum(py_type)
|
65
|
-
|
69
|
+
enum_type = Enum(name=py_type.__name__)
|
70
|
+
if not nested:
|
71
|
+
enum_type.set_generative()
|
72
|
+
return enum_type
|
66
73
|
elif py_type in (CArray, list):
|
67
74
|
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
68
75
|
return None
|
classiq/qmod/qfunc.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
import warnings
|
2
1
|
from typing import Callable, Literal, Optional, Union, overload
|
3
2
|
|
4
|
-
from classiq.interface.exceptions import
|
3
|
+
from classiq.interface.exceptions import ClassiqInternalError
|
5
4
|
|
6
5
|
from classiq.qmod.global_declarative_switch import get_global_declarative_switch
|
7
6
|
from classiq.qmod.quantum_callable import QCallable
|
@@ -57,23 +56,7 @@ def qfunc(
|
|
57
56
|
synthesize_separately: bool = False,
|
58
57
|
unchecked: Optional[list[str]] = None,
|
59
58
|
) -> Union[Callable[[Callable], QCallable], QCallable]:
|
60
|
-
if generative is
|
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:
|
59
|
+
if generative is None:
|
77
60
|
generative = True
|
78
61
|
if get_global_declarative_switch():
|
79
62
|
generative = False
|
classiq/qmod/qmod_constant.py
CHANGED
@@ -5,10 +5,7 @@ from typing import TYPE_CHECKING, Any, Optional, cast, get_origin
|
|
5
5
|
from classiq.interface.exceptions import ClassiqError, ClassiqValueError
|
6
6
|
from classiq.interface.generator.constant import Constant
|
7
7
|
from classiq.interface.generator.expressions.expression import Expression
|
8
|
-
from classiq.interface.generator.functions.classical_type import
|
9
|
-
ClassicalArray,
|
10
|
-
ClassicalList,
|
11
|
-
)
|
8
|
+
from classiq.interface.generator.functions.classical_type import ClassicalArray
|
12
9
|
|
13
10
|
from classiq.qmod.cparam import CArray, CParamScalar
|
14
11
|
from classiq.qmod.declaration_inferrer import python_type_to_qmod
|
@@ -118,7 +115,7 @@ class QConstant(SymbolicExpr):
|
|
118
115
|
if qmod_type is None:
|
119
116
|
raise ClassiqError("Invalid QMOD type")
|
120
117
|
|
121
|
-
if not isinstance(qmod_type,
|
118
|
+
if not isinstance(qmod_type, ClassicalArray):
|
122
119
|
raise ClassiqError("Invalid subscript to non-list constant")
|
123
120
|
|
124
121
|
return CParamList(
|
classiq/qmod/qmod_parameter.py
CHANGED
@@ -4,7 +4,6 @@ from classiq.interface.exceptions import ClassiqInternalError, ClassiqValueError
|
|
4
4
|
from classiq.interface.generator.functions.classical_type import (
|
5
5
|
Bool,
|
6
6
|
ClassicalArray,
|
7
|
-
ClassicalList,
|
8
7
|
ClassicalTuple,
|
9
8
|
ClassicalType,
|
10
9
|
Integer,
|
@@ -42,7 +41,7 @@ class CParamList(CParam):
|
|
42
41
|
def __init__(
|
43
42
|
self,
|
44
43
|
expr: str,
|
45
|
-
list_type: Union[
|
44
|
+
list_type: Union[ClassicalArray, ClassicalTuple],
|
46
45
|
qmodule: ModelStateContainer,
|
47
46
|
) -> None:
|
48
47
|
super().__init__(expr)
|
@@ -149,7 +148,7 @@ def create_param(
|
|
149
148
|
decl = ctype.classical_struct_decl
|
150
149
|
ctype = Struct(name=ctype.name)
|
151
150
|
ctype.set_classical_struct_decl(decl)
|
152
|
-
if isinstance(ctype, (
|
151
|
+
if isinstance(ctype, (ClassicalArray, ClassicalTuple)):
|
153
152
|
return CParamList(expr_str, ctype, qmodule=qmodule)
|
154
153
|
elif isinstance(ctype, Struct):
|
155
154
|
return CParamStruct(expr_str, ctype, qmodule=qmodule)
|
@@ -164,8 +163,6 @@ def get_qmod_type(ctype: ClassicalType) -> type:
|
|
164
163
|
return CReal
|
165
164
|
elif isinstance(ctype, Bool):
|
166
165
|
return CBool
|
167
|
-
elif isinstance(ctype, ClassicalList):
|
168
|
-
return CArray[get_qmod_type(ctype.element_type)] # type: ignore[misc]
|
169
166
|
elif isinstance(ctype, ClassicalArray):
|
170
167
|
if ctype.length is None:
|
171
168
|
return CArray[get_qmod_type(ctype.element_type)] # type: ignore[misc]
|
classiq/qmod/qmod_variable.py
CHANGED
@@ -34,19 +34,20 @@ from classiq.interface.generator.expressions.proxies.quantum.qmod_qarray_proxy i
|
|
34
34
|
ILLEGAL_SLICE_MSG,
|
35
35
|
ILLEGAL_SLICING_STEP_MSG,
|
36
36
|
)
|
37
|
+
from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
|
37
38
|
from classiq.interface.generator.functions.port_declaration import (
|
38
39
|
PortDeclarationDirection,
|
39
40
|
)
|
40
41
|
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
41
|
-
from classiq.interface.generator.functions.type_name import TypeName
|
42
|
+
from classiq.interface.generator.functions.type_name import Struct, TypeName
|
42
43
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
44
|
+
from classiq.interface.helpers.classproperty import classproperty
|
43
45
|
from classiq.interface.model.handle_binding import (
|
44
46
|
FieldHandleBinding,
|
45
47
|
HandleBinding,
|
46
48
|
SlicedHandleBinding,
|
47
49
|
SubscriptHandleBinding,
|
48
50
|
)
|
49
|
-
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
50
51
|
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
51
52
|
AmplitudeLoadingOperation,
|
52
53
|
)
|
@@ -73,7 +74,7 @@ from classiq.qmod.quantum_callable import QCallable
|
|
73
74
|
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
74
75
|
from classiq.qmod.semantics.validation.types_validation import validate_qstruct
|
75
76
|
from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
|
76
|
-
from classiq.qmod.symbolic_type import SymbolicTypes
|
77
|
+
from classiq.qmod.symbolic_type import SYMBOLIC_TYPES, SymbolicTypes
|
77
78
|
from classiq.qmod.utilities import (
|
78
79
|
get_source_ref,
|
79
80
|
unwrap_forward_ref,
|
@@ -103,9 +104,6 @@ def _infer_variable_name(name: Any, depth: int) -> Any:
|
|
103
104
|
return name
|
104
105
|
|
105
106
|
|
106
|
-
_SYMBOLIC_TYPES = tuple(get_origin(t) or t for t in get_args(SymbolicTypes))
|
107
|
-
|
108
|
-
|
109
107
|
class QVar(Symbolic):
|
110
108
|
CONSTRUCTOR_DEPTH: int = 1
|
111
109
|
|
@@ -136,7 +134,7 @@ class QVar(Symbolic):
|
|
136
134
|
return self._base_handle
|
137
135
|
|
138
136
|
@abc.abstractmethod
|
139
|
-
def get_qmod_type(self) ->
|
137
|
+
def get_qmod_type(self) -> ConcreteQuantumType:
|
140
138
|
raise NotImplementedError()
|
141
139
|
|
142
140
|
@classmethod
|
@@ -164,6 +162,14 @@ class QVar(Symbolic):
|
|
164
162
|
return self.get_qmod_type().type_name
|
165
163
|
|
166
164
|
|
165
|
+
class QmodExpressionCreator(Protocol):
|
166
|
+
"""
|
167
|
+
A callable that creates a Qmod expression from the provided QVars.
|
168
|
+
"""
|
169
|
+
|
170
|
+
def __call__(self, **kwargs: QVar) -> SymbolicExpr: ...
|
171
|
+
|
172
|
+
|
167
173
|
_Q = TypeVar("_Q", bound=QVar)
|
168
174
|
Output = Annotated[_Q, PortDeclarationDirection.Output]
|
169
175
|
Input = Annotated[_Q, PortDeclarationDirection.Input]
|
@@ -221,7 +227,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
221
227
|
)
|
222
228
|
|
223
229
|
def __ior__(self, other: Any) -> Self:
|
224
|
-
if not isinstance(other,
|
230
|
+
if not isinstance(other, SYMBOLIC_TYPES):
|
225
231
|
raise TypeError(
|
226
232
|
f"Invalid argument {other!r} for out-of-place arithmetic operation"
|
227
233
|
)
|
@@ -232,7 +238,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
232
238
|
return self
|
233
239
|
|
234
240
|
def __ixor__(self, other: Any) -> Self:
|
235
|
-
if not isinstance(other,
|
241
|
+
if not isinstance(other, SYMBOLIC_TYPES):
|
236
242
|
raise TypeError(
|
237
243
|
f"Invalid argument {other!r} for in-place arithmetic operation"
|
238
244
|
)
|
@@ -243,7 +249,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
243
249
|
return self
|
244
250
|
|
245
251
|
def __iadd__(self, other: Any) -> Self:
|
246
|
-
if not isinstance(other,
|
252
|
+
if not isinstance(other, SYMBOLIC_TYPES):
|
247
253
|
raise TypeError(
|
248
254
|
f"Invalid argument {other!r} for in-place arithmetic operation"
|
249
255
|
)
|
@@ -254,7 +260,7 @@ class QScalar(QVar, SymbolicExpr):
|
|
254
260
|
return self
|
255
261
|
|
256
262
|
def __imul__(self, other: Any) -> Self:
|
257
|
-
if not isinstance(other,
|
263
|
+
if not isinstance(other, SYMBOLIC_TYPES):
|
258
264
|
raise TypeError(
|
259
265
|
f"Invalid argument {other!r} for out of ampltiude encoding operation"
|
260
266
|
)
|
@@ -273,7 +279,7 @@ class QBit(QScalar):
|
|
273
279
|
) -> "QBit":
|
274
280
|
return QBit(origin, _expr_str=expr_str)
|
275
281
|
|
276
|
-
def get_qmod_type(self) ->
|
282
|
+
def get_qmod_type(self) -> ConcreteQuantumType:
|
277
283
|
return QuantumBit()
|
278
284
|
|
279
285
|
|
@@ -329,7 +335,7 @@ class QNum(Generic[_P], QScalar):
|
|
329
335
|
) -> "QNum":
|
330
336
|
return QNum(origin, *_get_qnum_attributes(type_hint), _expr_str=expr_str)
|
331
337
|
|
332
|
-
def get_qmod_type(self) ->
|
338
|
+
def get_qmod_type(self) -> ConcreteQuantumType:
|
333
339
|
return QuantumNumeric(
|
334
340
|
size=self._size,
|
335
341
|
is_signed=self._is_signed,
|
@@ -498,8 +504,15 @@ class QStruct(QVar):
|
|
498
504
|
setattr(self, field_name, var)
|
499
505
|
super().__init__(name, expr_str=_expr_str)
|
500
506
|
|
501
|
-
def get_qmod_type(self) ->
|
502
|
-
|
507
|
+
def get_qmod_type(self) -> ConcreteQuantumType:
|
508
|
+
classical_type = Struct(name=self._struct_name)
|
509
|
+
classical_type.set_fields(
|
510
|
+
{
|
511
|
+
field_name: field_var.get_qmod_type()
|
512
|
+
for field_name, field_var in self._fields.items()
|
513
|
+
}
|
514
|
+
)
|
515
|
+
return classical_type
|
503
516
|
|
504
517
|
@classmethod
|
505
518
|
def to_qvar(
|
@@ -529,9 +542,23 @@ class QStruct(QVar):
|
|
529
542
|
_expr_str=expr_str,
|
530
543
|
)
|
531
544
|
|
545
|
+
@classproperty
|
546
|
+
def num_qubits(cls) -> int: # noqa: N805
|
547
|
+
"""
|
548
|
+
The total number of qubits in this quantum struct.
|
549
|
+
Raises an error if the struct doesn't have a fixed size.
|
550
|
+
"""
|
551
|
+
qvar = cls.to_qvar(HandleBinding(name="dummy"), type_hint=cls, expr_str=None)
|
552
|
+
quantum_type = qvar.get_qmod_type()
|
553
|
+
if not quantum_type.has_size_in_bits:
|
554
|
+
raise ClassiqValueError(
|
555
|
+
f"Could not infer the size of struct {qvar._struct_name!r}"
|
556
|
+
)
|
557
|
+
return quantum_type.size_in_bits
|
558
|
+
|
532
559
|
|
533
|
-
def
|
534
|
-
return _create_qvar_for_qtype(
|
560
|
+
def create_qvar_from_quantum_type(quantum_type: ConcreteQuantumType, name: str) -> QVar:
|
561
|
+
return _create_qvar_for_qtype(quantum_type, HandleBinding(name=name))
|
535
562
|
|
536
563
|
|
537
564
|
def _create_qvar_for_qtype(
|
@@ -689,17 +716,27 @@ def _get_quantum_bit_vector(type_hint: type[QArray]) -> QuantumBitvector:
|
|
689
716
|
return QuantumBitvector(element_type=element_type, length=length_expr)
|
690
717
|
|
691
718
|
|
692
|
-
def _get_quantum_struct(type_hint: type[QStruct]) ->
|
693
|
-
_register_qstruct(type_hint, qmodule=QMODULE)
|
694
|
-
|
719
|
+
def _get_quantum_struct(type_hint: type[QStruct]) -> Struct:
|
720
|
+
decl = _register_qstruct(type_hint, qmodule=QMODULE)
|
721
|
+
classical_type = Struct(name=type_hint.__name__)
|
722
|
+
if decl is not None:
|
723
|
+
classical_type.set_fields(
|
724
|
+
{
|
725
|
+
field_name: field_type.model_copy(deep=True)
|
726
|
+
for field_name, field_type in decl.fields.items()
|
727
|
+
}
|
728
|
+
)
|
729
|
+
return classical_type
|
695
730
|
|
696
731
|
|
697
732
|
def _register_qstruct(
|
698
733
|
type_hint: type[QStruct], *, qmodule: ModelStateContainer
|
699
|
-
) ->
|
734
|
+
) -> Optional[QStructDeclaration]:
|
700
735
|
struct_name = type_hint.__name__
|
701
|
-
if type_hint is QStruct
|
702
|
-
return
|
736
|
+
if type_hint is QStruct:
|
737
|
+
return None
|
738
|
+
if struct_name in qmodule.qstruct_decls:
|
739
|
+
return qmodule.qstruct_decls[struct_name]
|
703
740
|
|
704
741
|
# temp assignment for recursive qstruct definitions
|
705
742
|
qmodule.qstruct_decls[struct_name] = QStructDeclaration(name=struct_name)
|
@@ -714,6 +751,7 @@ def _register_qstruct(
|
|
714
751
|
qmodule.qstruct_decls[struct_name] = struct_decl
|
715
752
|
QStructAnnotator().visit(struct_decl)
|
716
753
|
validate_qstruct(struct_decl)
|
754
|
+
return struct_decl
|
717
755
|
|
718
756
|
|
719
757
|
def _validate_fields(type_hint: type[QStruct]) -> None:
|
@@ -68,7 +68,7 @@ from classiq.qmod.qmod_parameter import (
|
|
68
68
|
)
|
69
69
|
from classiq.qmod.qmod_variable import (
|
70
70
|
QVar,
|
71
|
-
|
71
|
+
create_qvar_from_quantum_type,
|
72
72
|
)
|
73
73
|
from classiq.qmod.quantum_callable import QCallable, QExpandableInterface
|
74
74
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
@@ -135,7 +135,7 @@ class QExpandable(QCallable, QExpandableInterface, ABC):
|
|
135
135
|
) -> None:
|
136
136
|
self.append_statement_to_body(
|
137
137
|
VariableDeclarationStatement(
|
138
|
-
name=name,
|
138
|
+
name=name, qmod_type=qtype, source_ref=source_ref
|
139
139
|
)
|
140
140
|
)
|
141
141
|
|
@@ -163,7 +163,9 @@ class QExpandable(QCallable, QExpandableInterface, ABC):
|
|
163
163
|
create_param(actual_name, arg.classical_type, self._qmodule)
|
164
164
|
)
|
165
165
|
elif isinstance(arg, AnonPortDeclaration):
|
166
|
-
result.append(
|
166
|
+
result.append(
|
167
|
+
create_qvar_from_quantum_type(arg.quantum_type, actual_name)
|
168
|
+
)
|
167
169
|
else:
|
168
170
|
assert isinstance(arg, AnonQuantumOperandDeclaration)
|
169
171
|
result.append(QTerminalCallable(arg, idx))
|
classiq/qmod/quantum_function.py
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
import ast
|
2
2
|
import functools
|
3
|
+
import warnings
|
3
4
|
from abc import abstractmethod
|
4
5
|
from dataclasses import is_dataclass
|
5
6
|
from enum import EnumMeta
|
6
7
|
from inspect import isclass
|
7
8
|
from typing import Any, Callable, Optional, get_origin
|
8
9
|
|
9
|
-
from classiq.interface.exceptions import ClassiqError
|
10
|
+
from classiq.interface.exceptions import ClassiqDeprecationWarning, ClassiqError
|
10
11
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
11
12
|
from classiq.interface.generator.functions.port_declaration import (
|
12
13
|
PortDeclarationDirection,
|
@@ -28,7 +29,7 @@ from classiq.qmod.declaration_inferrer import infer_func_decl, is_qvar
|
|
28
29
|
from classiq.qmod.generative import set_frontend_interpreter
|
29
30
|
from classiq.qmod.global_declarative_switch import get_global_declarative_switch
|
30
31
|
from classiq.qmod.qmod_constant import QConstant
|
31
|
-
from classiq.qmod.qmod_parameter import CArray
|
32
|
+
from classiq.qmod.qmod_parameter import CArray, CParamList
|
32
33
|
from classiq.qmod.quantum_callable import QCallable, QCallableList
|
33
34
|
from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
|
34
35
|
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
@@ -101,7 +102,12 @@ class QFunc(BaseQFunc):
|
|
101
102
|
) -> None:
|
102
103
|
_validate_no_gen_params(py_callable.__annotations__)
|
103
104
|
super().__init__(py_callable, compilation_metadata)
|
104
|
-
|
105
|
+
if compilation_metadata is not None and compilation_metadata.unchecked:
|
106
|
+
self.compilation_metadata: Optional[CompilationMetadata] = (
|
107
|
+
CompilationMetadata(unchecked=compilation_metadata.unchecked)
|
108
|
+
)
|
109
|
+
else:
|
110
|
+
self.compilation_metadata = None
|
105
111
|
|
106
112
|
@property
|
107
113
|
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
@@ -213,6 +219,7 @@ class QFunc(BaseQFunc):
|
|
213
219
|
|
214
220
|
|
215
221
|
class ExternalQFunc(QTerminalCallable):
|
222
|
+
FRAME_DEPTH = 2 # FIXME: Remove (CLS-2912)
|
216
223
|
_decl: NamedParamsQuantumFunctionDeclaration
|
217
224
|
|
218
225
|
def __init__(self, py_callable: Callable) -> None:
|
@@ -237,6 +244,44 @@ class ExternalQFunc(QTerminalCallable):
|
|
237
244
|
def pure_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
238
245
|
return self.func_decl
|
239
246
|
|
247
|
+
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
248
|
+
if self._py_callable.__name__ == "parametric_suzuki_trotter":
|
249
|
+
warnings.warn(
|
250
|
+
(
|
251
|
+
"Function 'parametric_suzuki_trotter' is deprecated and will no "
|
252
|
+
"longer be supported starting on 21/7/2025 at the earliest. "
|
253
|
+
"Instead, use 'multi_suzuki_trotter'."
|
254
|
+
),
|
255
|
+
ClassiqDeprecationWarning,
|
256
|
+
stacklevel=2,
|
257
|
+
)
|
258
|
+
if self._py_callable.__name__ == "sparse_suzuki_trotter":
|
259
|
+
warnings.warn(
|
260
|
+
(
|
261
|
+
"Function 'sparse_suzuki_trotter' is deprecated and will no "
|
262
|
+
"longer be supported starting on 21/7/2025 at the earliest. "
|
263
|
+
"Instead, use 'suzuki_trotter'."
|
264
|
+
),
|
265
|
+
ClassiqDeprecationWarning,
|
266
|
+
stacklevel=2,
|
267
|
+
)
|
268
|
+
if (
|
269
|
+
self._py_callable.__name__ == "suzuki_trotter"
|
270
|
+
and len(args) > 0
|
271
|
+
and isinstance(args[0], (list, CParamList))
|
272
|
+
):
|
273
|
+
warnings.warn(
|
274
|
+
(
|
275
|
+
"Parameter type CArray[PauliTerm] to function 'suzuki_trotter' is "
|
276
|
+
"deprecated and will no longer be supported starting on 21/7/2025 "
|
277
|
+
"at the earliest. Instead, send a 'SparsePauliOp' (see "
|
278
|
+
"https://docs.classiq.io/latest/qmod-reference/language-reference/classical-types/#hamiltonians)."
|
279
|
+
),
|
280
|
+
ClassiqDeprecationWarning,
|
281
|
+
stacklevel=2,
|
282
|
+
)
|
283
|
+
super().__call__(*args, **kwargs)
|
284
|
+
|
240
285
|
|
241
286
|
class GenerativeQFunc(BaseQFunc):
|
242
287
|
FRAME_DEPTH = 3
|
@@ -261,7 +306,7 @@ class GenerativeQFunc(BaseQFunc):
|
|
261
306
|
|
262
307
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
263
308
|
if get_global_declarative_switch():
|
264
|
-
return QFunc(self._py_callable)(*args, **kwargs)
|
309
|
+
return QFunc(self._py_callable, self.compilation_metadata)(*args, **kwargs)
|
265
310
|
if self.func_decl.name not in self._qmodule.generative_functions:
|
266
311
|
self._qmodule.generative_functions[self.func_decl.name] = self
|
267
312
|
if self._func_decl is None:
|
@@ -45,7 +45,7 @@ class QStructAnnotator(ModelVisitor):
|
|
45
45
|
return
|
46
46
|
self._visited.add(type_name)
|
47
47
|
new_fields = {
|
48
|
-
field_name: field_type.model_copy()
|
48
|
+
field_name: field_type.model_copy(deep=True)
|
49
49
|
for field_name, field_type in decl.variables.items()
|
50
50
|
}
|
51
51
|
self.visit(new_fields)
|
@@ -1,8 +1,5 @@
|
|
1
1
|
from classiq.interface.exceptions import ClassiqExpansionError, ClassiqValueError
|
2
|
-
from classiq.interface.generator.functions.classical_type import
|
3
|
-
ClassicalArray,
|
4
|
-
ClassicalList,
|
5
|
-
)
|
2
|
+
from classiq.interface.generator.functions.classical_type import ClassicalArray
|
6
3
|
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
7
4
|
from classiq.interface.generator.functions.port_declaration import (
|
8
5
|
PortDeclarationDirection,
|
@@ -31,11 +28,6 @@ def _validate_main_param(param: PositionalArg) -> None:
|
|
31
28
|
def _validate_main_classical_param_type(
|
32
29
|
param: ConcreteClassicalType, param_name: str
|
33
30
|
) -> None:
|
34
|
-
if isinstance(param, ClassicalList):
|
35
|
-
raise ClassiqExpansionError(
|
36
|
-
f"Classical array parameter {param_name!r} of function 'main' must "
|
37
|
-
f"specify array length",
|
38
|
-
)
|
39
31
|
if isinstance(param, ClassicalArray):
|
40
32
|
if param.length is None:
|
41
33
|
raise ClassiqExpansionError(
|
classiq/qmod/symbolic_type.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
from typing import Union
|
1
|
+
from typing import Union, get_args, get_origin
|
2
2
|
|
3
3
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
4
4
|
|
5
5
|
SymbolicTypes = Union[SymbolicExpr, int, float, bool, tuple["SymbolicTypes", ...]]
|
6
|
+
SYMBOLIC_TYPES = tuple(get_origin(t) or t for t in get_args(SymbolicTypes))
|
classiq/qmod/utilities.py
CHANGED
classiq/qmod/write_qmod.py
CHANGED
@@ -2,12 +2,12 @@ import json
|
|
2
2
|
from pathlib import Path
|
3
3
|
from typing import Optional, Union
|
4
4
|
|
5
|
+
from classiq.interface.constants import DEFAULT_DECIMAL_PRECISION
|
5
6
|
from classiq.interface.model.model import Model, SerializedModel
|
6
7
|
|
7
8
|
from classiq.qmod.global_declarative_switch import set_global_declarative_switch
|
8
9
|
from classiq.qmod.native.pretty_printer import DSLPrettyPrinter
|
9
10
|
from classiq.qmod.quantum_function import GenerativeQFunc, QFunc
|
10
|
-
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
11
11
|
|
12
12
|
_QMOD_SUFFIX = "qmod"
|
13
13
|
_SYNTHESIS_OPTIONS_SUFFIX = "synthesis_options.json"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: classiq
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.85.0
|
4
4
|
Summary: Classiq's Python SDK for quantum computing
|
5
5
|
License: Proprietary
|
6
6
|
Keywords: quantum computing,quantum circuits,quantum algorithms,QAD,QDL
|
@@ -27,6 +27,7 @@ Classifier: Topic :: Software Development :: Compilers
|
|
27
27
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
28
28
|
Classifier: Typing :: Typed
|
29
29
|
Provides-Extra: analyzer-sdk
|
30
|
+
Provides-Extra: chemistry
|
30
31
|
Provides-Extra: qml
|
31
32
|
Requires-Dist: ConfigArgParse (>=1.5.3,<2.0.0)
|
32
33
|
Requires-Dist: Pyomo (>=6.5,<6.6)
|
@@ -41,6 +42,8 @@ Requires-Dist: notebook ; extra == "analyzer-sdk"
|
|
41
42
|
Requires-Dist: numexpr (>=2.7.3,<3.0.0)
|
42
43
|
Requires-Dist: numpy (>=1.20.1,<2.0.0) ; python_version < "3.12"
|
43
44
|
Requires-Dist: numpy (>=1.26.0,<2.0.0) ; python_version >= "3.12"
|
45
|
+
Requires-Dist: openfermion ; extra == "chemistry"
|
46
|
+
Requires-Dist: openfermionpyscf ; extra == "chemistry"
|
44
47
|
Requires-Dist: packaging (>=23.2,<24.0)
|
45
48
|
Requires-Dist: pandas (>=1.4.0,<3.0.0)
|
46
49
|
Requires-Dist: plotly (>=5.7.0,<6.0.0)
|