classiq 0.75.0__py3-none-any.whl → 0.77.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 +36 -0
- classiq/analyzer/show_interactive_hack.py +58 -2
- classiq/applications/chemistry/chemistry_model_constructor.py +15 -7
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +11 -1
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +8 -7
- classiq/applications/qnn/gradients/quantum_gradient.py +3 -5
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -2
- classiq/applications/qnn/qlayer.py +14 -19
- classiq/applications/qnn/types.py +1 -4
- classiq/execution/__init__.py +3 -0
- classiq/execution/execution_session.py +3 -16
- classiq/execution/qnn.py +2 -2
- classiq/execution/user_budgets.py +38 -0
- classiq/executor.py +7 -19
- classiq/interface/_version.py +1 -1
- classiq/interface/debug_info/debug_info.py +16 -2
- classiq/interface/executor/user_budget.py +56 -0
- classiq/interface/generator/application_apis/finance_declarations.py +3 -0
- classiq/interface/generator/expressions/atomic_expression_functions.py +3 -0
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +30 -124
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +45 -21
- classiq/interface/generator/expressions/proxies/classical/qmod_struct_instance.py +7 -0
- classiq/interface/generator/expressions/proxies/classical/utils.py +12 -11
- classiq/interface/generator/expressions/proxies/quantum/qmod_qarray_proxy.py +6 -15
- classiq/interface/generator/expressions/proxies/quantum/qmod_qscalar_proxy.py +22 -6
- classiq/interface/generator/expressions/proxies/quantum/qmod_sized_proxy.py +9 -4
- classiq/interface/generator/expressions/sympy_supported_expressions.py +1 -0
- classiq/interface/generator/functions/classical_type.py +6 -1
- classiq/interface/generator/functions/type_name.py +7 -2
- classiq/interface/generator/functions/type_qualifier.py +15 -0
- classiq/interface/generator/model/preferences/preferences.py +7 -0
- classiq/interface/generator/quantum_program.py +5 -19
- classiq/interface/helpers/backward_compatibility.py +9 -0
- classiq/interface/helpers/datastructures.py +6 -0
- classiq/interface/model/handle_binding.py +8 -0
- classiq/interface/model/model.py +3 -6
- classiq/interface/model/port_declaration.py +1 -2
- classiq/interface/model/quantum_function_call.py +31 -1
- classiq/interface/model/quantum_lambda_function.py +2 -1
- classiq/interface/model/quantum_statement.py +14 -1
- classiq/interface/server/routes.py +6 -0
- classiq/interface/source_reference.py +7 -2
- classiq/model_expansions/atomic_expression_functions_defs.py +62 -19
- classiq/model_expansions/capturing/captured_vars.py +18 -6
- classiq/model_expansions/closure.py +5 -0
- classiq/model_expansions/evaluators/arg_type_match.py +2 -2
- classiq/model_expansions/evaluators/argument_types.py +3 -3
- classiq/model_expansions/evaluators/classical_expression.py +9 -9
- classiq/model_expansions/evaluators/classical_type_inference.py +17 -6
- classiq/model_expansions/evaluators/parameter_types.py +45 -24
- classiq/model_expansions/expression_evaluator.py +21 -12
- classiq/model_expansions/function_builder.py +45 -0
- classiq/model_expansions/generative_functions.py +62 -35
- classiq/model_expansions/interpreters/base_interpreter.py +32 -7
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +9 -3
- classiq/model_expansions/interpreters/generative_interpreter.py +17 -5
- classiq/model_expansions/quantum_operations/allocate.py +8 -3
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +221 -20
- classiq/model_expansions/quantum_operations/bind.py +54 -30
- classiq/model_expansions/quantum_operations/block_evaluator.py +42 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +35 -18
- classiq/model_expansions/quantum_operations/composite_emitter.py +1 -1
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +23 -9
- classiq/model_expansions/quantum_operations/emitter.py +21 -9
- classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -3
- classiq/model_expansions/scope.py +63 -10
- classiq/model_expansions/sympy_conversion/arithmetics.py +18 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +2 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +10 -1
- classiq/model_expansions/transformers/model_renamer.py +45 -7
- classiq/model_expansions/utils/handles_collector.py +1 -1
- classiq/model_expansions/visitors/symbolic_param_inference.py +3 -3
- classiq/model_expansions/visitors/variable_references.py +45 -9
- classiq/open_library/functions/lookup_table.py +1 -1
- classiq/open_library/functions/state_preparation.py +1 -1
- classiq/qmod/builtins/functions/allocation.py +2 -2
- classiq/qmod/builtins/functions/arithmetic.py +14 -12
- classiq/qmod/builtins/functions/standard_gates.py +23 -23
- classiq/qmod/create_model_function.py +21 -3
- classiq/qmod/declaration_inferrer.py +19 -7
- classiq/qmod/generative.py +9 -1
- classiq/qmod/global_declarative_switch.py +19 -0
- classiq/qmod/native/expression_to_qmod.py +4 -0
- classiq/qmod/native/pretty_printer.py +12 -3
- classiq/qmod/pretty_print/pretty_printer.py +5 -1
- classiq/qmod/python_classical_type.py +4 -5
- classiq/qmod/qfunc.py +31 -23
- classiq/qmod/qmod_constant.py +15 -7
- classiq/qmod/qmod_variable.py +7 -1
- classiq/qmod/quantum_expandable.py +29 -1
- classiq/qmod/quantum_function.py +45 -25
- classiq/qmod/semantics/lambdas.py +6 -2
- classiq/qmod/semantics/validation/main_validation.py +17 -4
- classiq/qmod/symbolic.py +8 -19
- classiq/qmod/symbolic_expr.py +26 -0
- classiq/qmod/write_qmod.py +36 -10
- classiq/synthesis.py +24 -37
- classiq/visualization.py +35 -0
- {classiq-0.75.0.dist-info → classiq-0.77.0.dist-info}/METADATA +1 -1
- {classiq-0.75.0.dist-info → classiq-0.77.0.dist-info}/RECORD +101 -96
- {classiq-0.75.0.dist-info → classiq-0.77.0.dist-info}/WHEEL +0 -0
@@ -2,7 +2,7 @@ from typing import Literal
|
|
2
2
|
|
3
3
|
from classiq.qmod.qfunc import qfunc
|
4
4
|
from classiq.qmod.qmod_parameter import CReal
|
5
|
-
from classiq.qmod.qmod_variable import QArray, QBit
|
5
|
+
from classiq.qmod.qmod_variable import Const, QArray, QBit, QFree
|
6
6
|
|
7
7
|
|
8
8
|
@qfunc(external=True)
|
@@ -25,7 +25,7 @@ def H(target: QBit) -> None:
|
|
25
25
|
|
26
26
|
|
27
27
|
@qfunc(external=True)
|
28
|
-
def X(target: QBit) -> None:
|
28
|
+
def X(target: QFree[QBit]) -> None:
|
29
29
|
"""
|
30
30
|
[Qmod core-library function]
|
31
31
|
|
@@ -44,7 +44,7 @@ def X(target: QBit) -> None:
|
|
44
44
|
|
45
45
|
|
46
46
|
@qfunc(external=True)
|
47
|
-
def Y(target: QBit) -> None:
|
47
|
+
def Y(target: QFree[QBit]) -> None:
|
48
48
|
"""
|
49
49
|
[Qmod core-library function]
|
50
50
|
|
@@ -63,7 +63,7 @@ def Y(target: QBit) -> None:
|
|
63
63
|
|
64
64
|
|
65
65
|
@qfunc(external=True)
|
66
|
-
def Z(target: QBit) -> None:
|
66
|
+
def Z(target: Const[QBit]) -> None:
|
67
67
|
"""
|
68
68
|
[Qmod core-library function]
|
69
69
|
|
@@ -82,7 +82,7 @@ def Z(target: QBit) -> None:
|
|
82
82
|
|
83
83
|
|
84
84
|
@qfunc(external=True)
|
85
|
-
def I(target: QBit) -> None:
|
85
|
+
def I(target: Const[QBit]) -> None:
|
86
86
|
"""
|
87
87
|
[Qmod core-library function]
|
88
88
|
|
@@ -101,7 +101,7 @@ def I(target: QBit) -> None:
|
|
101
101
|
|
102
102
|
|
103
103
|
@qfunc(external=True)
|
104
|
-
def S(target: QBit) -> None:
|
104
|
+
def S(target: Const[QBit]) -> None:
|
105
105
|
"""
|
106
106
|
[Qmod core-library function]
|
107
107
|
|
@@ -120,7 +120,7 @@ def S(target: QBit) -> None:
|
|
120
120
|
|
121
121
|
|
122
122
|
@qfunc(external=True)
|
123
|
-
def T(target: QBit) -> None:
|
123
|
+
def T(target: Const[QBit]) -> None:
|
124
124
|
"""
|
125
125
|
[Qmod core-library function]
|
126
126
|
|
@@ -139,7 +139,7 @@ def T(target: QBit) -> None:
|
|
139
139
|
|
140
140
|
|
141
141
|
@qfunc(external=True)
|
142
|
-
def SDG(target: QBit) -> None:
|
142
|
+
def SDG(target: Const[QBit]) -> None:
|
143
143
|
"""
|
144
144
|
[Qmod core-library function]
|
145
145
|
|
@@ -158,7 +158,7 @@ def SDG(target: QBit) -> None:
|
|
158
158
|
|
159
159
|
|
160
160
|
@qfunc(external=True)
|
161
|
-
def TDG(target: QBit) -> None:
|
161
|
+
def TDG(target: Const[QBit]) -> None:
|
162
162
|
"""
|
163
163
|
[Qmod core-library function]
|
164
164
|
|
@@ -177,7 +177,7 @@ def TDG(target: QBit) -> None:
|
|
177
177
|
|
178
178
|
|
179
179
|
@qfunc(external=True)
|
180
|
-
def PHASE(theta: CReal, target: QBit) -> None:
|
180
|
+
def PHASE(theta: CReal, target: Const[QBit]) -> None:
|
181
181
|
"""
|
182
182
|
[Qmod core-library function]
|
183
183
|
|
@@ -239,7 +239,7 @@ def RY(theta: CReal, target: QBit) -> None:
|
|
239
239
|
|
240
240
|
|
241
241
|
@qfunc(external=True)
|
242
|
-
def RZ(theta: CReal, target: QBit) -> None:
|
242
|
+
def RZ(theta: CReal, target: Const[QBit]) -> None:
|
243
243
|
"""
|
244
244
|
[Qmod core-library function]
|
245
245
|
|
@@ -324,7 +324,7 @@ def RYY(theta: CReal, target: QArray[QBit, Literal[2]]) -> None:
|
|
324
324
|
|
325
325
|
|
326
326
|
@qfunc(external=True)
|
327
|
-
def RZZ(theta: CReal, target: QArray[QBit, Literal[2]]) -> None:
|
327
|
+
def RZZ(theta: CReal, target: Const[QArray[QBit, Literal[2]]]) -> None:
|
328
328
|
"""
|
329
329
|
[Qmod core-library function]
|
330
330
|
|
@@ -345,7 +345,7 @@ def RZZ(theta: CReal, target: QArray[QBit, Literal[2]]) -> None:
|
|
345
345
|
|
346
346
|
|
347
347
|
@qfunc(external=True)
|
348
|
-
def CH(ctrl: QBit, target: QBit) -> None:
|
348
|
+
def CH(ctrl: Const[QBit], target: QBit) -> None:
|
349
349
|
"""
|
350
350
|
[Qmod core-library function]
|
351
351
|
|
@@ -370,7 +370,7 @@ def CH(ctrl: QBit, target: QBit) -> None:
|
|
370
370
|
|
371
371
|
|
372
372
|
@qfunc(external=True)
|
373
|
-
def CX(ctrl: QBit, target: QBit) -> None:
|
373
|
+
def CX(ctrl: Const[QBit], target: QFree[QBit]) -> None:
|
374
374
|
"""
|
375
375
|
[Qmod core-library function]
|
376
376
|
|
@@ -395,7 +395,7 @@ def CX(ctrl: QBit, target: QBit) -> None:
|
|
395
395
|
|
396
396
|
|
397
397
|
@qfunc(external=True)
|
398
|
-
def CY(ctrl: QBit, target: QBit) -> None:
|
398
|
+
def CY(ctrl: Const[QBit], target: QFree[QBit]) -> None:
|
399
399
|
"""
|
400
400
|
[Qmod core-library function]
|
401
401
|
|
@@ -420,7 +420,7 @@ def CY(ctrl: QBit, target: QBit) -> None:
|
|
420
420
|
|
421
421
|
|
422
422
|
@qfunc(external=True)
|
423
|
-
def CZ(ctrl: QBit, target: QBit) -> None:
|
423
|
+
def CZ(ctrl: Const[QBit], target: Const[QBit]) -> None:
|
424
424
|
"""
|
425
425
|
[Qmod core-library function]
|
426
426
|
|
@@ -445,7 +445,7 @@ def CZ(ctrl: QBit, target: QBit) -> None:
|
|
445
445
|
|
446
446
|
|
447
447
|
@qfunc(external=True)
|
448
|
-
def CRX(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
448
|
+
def CRX(theta: CReal, ctrl: Const[QBit], target: QBit) -> None:
|
449
449
|
"""
|
450
450
|
[Qmod core-library function]
|
451
451
|
|
@@ -471,7 +471,7 @@ def CRX(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
|
471
471
|
|
472
472
|
|
473
473
|
@qfunc(external=True)
|
474
|
-
def CRY(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
474
|
+
def CRY(theta: CReal, ctrl: Const[QBit], target: QBit) -> None:
|
475
475
|
"""
|
476
476
|
[Qmod core-library function]
|
477
477
|
|
@@ -497,7 +497,7 @@ def CRY(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
|
497
497
|
|
498
498
|
|
499
499
|
@qfunc(external=True)
|
500
|
-
def CRZ(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
500
|
+
def CRZ(theta: CReal, ctrl: Const[QBit], target: Const[QBit]) -> None:
|
501
501
|
"""
|
502
502
|
[Qmod core-library function]
|
503
503
|
|
@@ -523,7 +523,7 @@ def CRZ(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
|
523
523
|
|
524
524
|
|
525
525
|
@qfunc(external=True)
|
526
|
-
def CPHASE(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
526
|
+
def CPHASE(theta: CReal, ctrl: Const[QBit], target: Const[QBit]) -> None:
|
527
527
|
"""
|
528
528
|
[Qmod core-library function]
|
529
529
|
|
@@ -549,7 +549,7 @@ def CPHASE(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
|
549
549
|
|
550
550
|
|
551
551
|
@qfunc(external=True)
|
552
|
-
def SWAP(qbit0: QBit, qbit1: QBit) -> None:
|
552
|
+
def SWAP(qbit0: QFree[QBit], qbit1: QFree[QBit]) -> None:
|
553
553
|
"""
|
554
554
|
[Qmod core-library function]
|
555
555
|
|
@@ -574,7 +574,7 @@ def SWAP(qbit0: QBit, qbit1: QBit) -> None:
|
|
574
574
|
|
575
575
|
|
576
576
|
@qfunc(external=True)
|
577
|
-
def IDENTITY(target: QArray[QBit]) -> None:
|
577
|
+
def IDENTITY(target: Const[QArray[QBit]]) -> None:
|
578
578
|
"""
|
579
579
|
[Qmod core-library function]
|
580
580
|
|
@@ -623,7 +623,7 @@ def U(theta: CReal, phi: CReal, lam: CReal, gam: CReal, target: QBit) -> None:
|
|
623
623
|
|
624
624
|
|
625
625
|
@qfunc(external=True)
|
626
|
-
def CCX(ctrl: QArray[QBit, Literal[2]], target: QBit) -> None:
|
626
|
+
def CCX(ctrl: Const[QArray[QBit, Literal[2]]], target: QFree[QBit]) -> None:
|
627
627
|
"""
|
628
628
|
[Qmod core-library function]
|
629
629
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Optional, Union
|
1
|
+
from typing import Optional, Union, cast
|
2
2
|
|
3
3
|
from classiq.interface.exceptions import ClassiqError
|
4
4
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
@@ -7,10 +7,26 @@ from classiq.interface.generator.model.preferences.preferences import Preference
|
|
7
7
|
from classiq.interface.model.model import MAIN_FUNCTION_NAME, SerializedModel
|
8
8
|
|
9
9
|
from classiq.qmod.classical_function import CFunc
|
10
|
-
from classiq.qmod.quantum_function import GenerativeQFunc, QFunc
|
10
|
+
from classiq.qmod.quantum_function import BaseQFunc, GenerativeQFunc, QFunc
|
11
11
|
from classiq.qmod.write_qmod import write_qmod
|
12
12
|
|
13
13
|
|
14
|
+
class _EntryPointWrapper(str):
|
15
|
+
entry_point: BaseQFunc
|
16
|
+
|
17
|
+
|
18
|
+
def add_entry_point(
|
19
|
+
new_model: SerializedModel, old_model: SerializedModel
|
20
|
+
) -> SerializedModel:
|
21
|
+
if not hasattr(old_model, "entry_point"):
|
22
|
+
return new_model
|
23
|
+
new_model_with_entry_point = _EntryPointWrapper(new_model)
|
24
|
+
new_model_with_entry_point.entry_point = cast(
|
25
|
+
_EntryPointWrapper, old_model
|
26
|
+
).entry_point
|
27
|
+
return cast(SerializedModel, new_model_with_entry_point)
|
28
|
+
|
29
|
+
|
14
30
|
def create_model(
|
15
31
|
entry_point: Union[QFunc, GenerativeQFunc],
|
16
32
|
constraints: Optional[Constraints] = None,
|
@@ -48,7 +64,9 @@ def create_model(
|
|
48
64
|
preferences,
|
49
65
|
classical_execution_function,
|
50
66
|
)
|
51
|
-
|
67
|
+
serialized_model = _EntryPointWrapper(model.get_model())
|
68
|
+
serialized_model.entry_point = entry_point
|
69
|
+
result = cast(SerializedModel, serialized_model)
|
52
70
|
|
53
71
|
if out_file is not None:
|
54
72
|
write_qmod(result, out_file)
|
@@ -19,6 +19,7 @@ from classiq.interface.generator.functions.concrete_types import ConcreteClassic
|
|
19
19
|
from classiq.interface.generator.functions.port_declaration import (
|
20
20
|
PortDeclarationDirection,
|
21
21
|
)
|
22
|
+
from classiq.interface.generator.functions.type_name import TypeName
|
22
23
|
from classiq.interface.generator.functions.type_qualifier import TypeQualifier
|
23
24
|
from classiq.interface.generator.types.enum_declaration import declaration_from_enum
|
24
25
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
@@ -40,6 +41,10 @@ from classiq.qmod.python_classical_type import PythonClassicalType
|
|
40
41
|
from classiq.qmod.qmod_variable import QVar, get_port_from_type_hint
|
41
42
|
from classiq.qmod.quantum_callable import QCallableList
|
42
43
|
from classiq.qmod.semantics.validation.type_hints import validate_annotation
|
44
|
+
from classiq.qmod.semantics.validation.types_validation import (
|
45
|
+
check_duplicate_types,
|
46
|
+
validate_cstruct,
|
47
|
+
)
|
43
48
|
from classiq.qmod.utilities import unmangle_keyword, version_portable_get_args
|
44
49
|
|
45
50
|
if sys.version_info[0:2] >= (3, 9):
|
@@ -61,14 +66,16 @@ class _PythonClassicalType(PythonClassicalType):
|
|
61
66
|
|
62
67
|
enum_decl = declaration_from_enum(py_type)
|
63
68
|
self.qmodule.enum_decls[py_type.__name__] = enum_decl
|
69
|
+
check_duplicate_types([enum_decl])
|
64
70
|
|
65
|
-
def register_struct(self, py_type: type) ->
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
def register_struct(self, py_type: type) -> TypeName:
|
72
|
+
classical_type = super().register_struct(py_type)
|
73
|
+
if self.qmodule is None:
|
74
|
+
return classical_type
|
75
|
+
all_decls = BUILTIN_STRUCT_DECLARATIONS | self.qmodule.type_decls
|
76
|
+
if py_type.__name__ in all_decls:
|
77
|
+
classical_type.set_classical_struct_decl(all_decls[py_type.__name__])
|
78
|
+
return classical_type
|
72
79
|
|
73
80
|
struct_decl = StructDeclaration(
|
74
81
|
name=py_type.__name__,
|
@@ -77,6 +84,11 @@ class _PythonClassicalType(PythonClassicalType):
|
|
77
84
|
},
|
78
85
|
)
|
79
86
|
self.qmodule.type_decls[py_type.__name__] = struct_decl
|
87
|
+
check_duplicate_types([struct_decl])
|
88
|
+
validate_cstruct(struct_decl)
|
89
|
+
|
90
|
+
classical_type.set_classical_struct_decl(struct_decl)
|
91
|
+
return classical_type
|
80
92
|
|
81
93
|
|
82
94
|
def python_type_to_qmod(
|
classiq/qmod/generative.py
CHANGED
@@ -4,6 +4,11 @@ from typing import TYPE_CHECKING, Any, Optional
|
|
4
4
|
|
5
5
|
from classiq.interface.exceptions import ClassiqError
|
6
6
|
from classiq.interface.generator.expressions.expression import Expression
|
7
|
+
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
8
|
+
AnyClassicalValue,
|
9
|
+
)
|
10
|
+
|
11
|
+
from classiq.qmod.cparam import CParamScalar
|
7
12
|
|
8
13
|
if TYPE_CHECKING:
|
9
14
|
from classiq.model_expansions.interpreters.generative_interpreter import (
|
@@ -41,4 +46,7 @@ def get_frontend_interpreter() -> "GenerativeInterpreter":
|
|
41
46
|
|
42
47
|
|
43
48
|
def interpret_expression(expr: str) -> Any:
|
44
|
-
|
49
|
+
val = get_frontend_interpreter().evaluate(Expression(expr=expr)).value
|
50
|
+
if isinstance(val, AnyClassicalValue):
|
51
|
+
return CParamScalar(str(val))
|
52
|
+
return val
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from collections.abc import Iterator
|
2
|
+
from contextlib import contextmanager
|
3
|
+
|
4
|
+
_DECLARATIVE_SWITCH = False
|
5
|
+
|
6
|
+
|
7
|
+
def get_global_declarative_switch() -> bool:
|
8
|
+
return _DECLARATIVE_SWITCH
|
9
|
+
|
10
|
+
|
11
|
+
@contextmanager
|
12
|
+
def set_global_declarative_switch() -> Iterator[None]:
|
13
|
+
global _DECLARATIVE_SWITCH
|
14
|
+
previous = _DECLARATIVE_SWITCH
|
15
|
+
_DECLARATIVE_SWITCH = True
|
16
|
+
try:
|
17
|
+
yield
|
18
|
+
finally:
|
19
|
+
_DECLARATIVE_SWITCH = previous
|
@@ -131,6 +131,10 @@ class ASTToQMODCode:
|
|
131
131
|
]
|
132
132
|
)
|
133
133
|
return f"{self.ast_to_code(node.args[0])} {{{initializer_list}}}"
|
134
|
+
elif func == "do_subscript":
|
135
|
+
if len(node.args) != 2:
|
136
|
+
raise AssertionError("Error parsing array access.")
|
137
|
+
return f"{self.ast_to_code(node.args[0])}[{self.ast_to_code(node.args[1])}]"
|
134
138
|
else:
|
135
139
|
return "{}({})".format(
|
136
140
|
func, ", ".join(self._cleaned_ast_to_code(arg) for arg in node.args)
|
@@ -26,6 +26,7 @@ from classiq.interface.generator.types.struct_declaration import StructDeclarati
|
|
26
26
|
from classiq.interface.generator.visitor import NodeType
|
27
27
|
from classiq.interface.model.allocate import Allocate
|
28
28
|
from classiq.interface.model.bind_operation import BindOperation
|
29
|
+
from classiq.interface.model.block import Block
|
29
30
|
from classiq.interface.model.classical_if import ClassicalIf
|
30
31
|
from classiq.interface.model.classical_parameter_declaration import (
|
31
32
|
AnonClassicalParameterDeclaration,
|
@@ -34,6 +35,7 @@ from classiq.interface.model.control import Control
|
|
34
35
|
from classiq.interface.model.handle_binding import (
|
35
36
|
FieldHandleBinding,
|
36
37
|
HandleBinding,
|
38
|
+
HandlesList,
|
37
39
|
SlicedHandleBinding,
|
38
40
|
SubscriptHandleBinding,
|
39
41
|
)
|
@@ -192,7 +194,7 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
192
194
|
def visit_AnonPortDeclaration(self, port_decl: AnonPortDeclaration) -> str:
|
193
195
|
qualifier_str = (
|
194
196
|
f"{port_decl.type_qualifier} "
|
195
|
-
if port_decl.type_qualifier
|
197
|
+
if port_decl.type_qualifier in [TypeQualifier.Const, TypeQualifier.QFree]
|
196
198
|
else ""
|
197
199
|
)
|
198
200
|
dir_str = (
|
@@ -308,8 +310,6 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
308
310
|
|
309
311
|
def visit_ClassicalIf(self, op: ClassicalIf) -> str:
|
310
312
|
classical_if = f"{self._indent}if ({self.visit(op.condition)}) {{\n"
|
311
|
-
if not op.then:
|
312
|
-
raise AssertionError('Expected non empty "then" block')
|
313
313
|
classical_if += self._visit_body(op.then)
|
314
314
|
|
315
315
|
if op.else_:
|
@@ -345,6 +345,12 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
345
345
|
invert_code += f"{self._indent}}}\n"
|
346
346
|
return invert_code
|
347
347
|
|
348
|
+
def visit_Block(self, block: Block) -> str:
|
349
|
+
invert_code = f"{self._indent}block {{\n"
|
350
|
+
invert_code += self._visit_body(block.statements)
|
351
|
+
invert_code += f"{self._indent}}}\n"
|
352
|
+
return invert_code
|
353
|
+
|
348
354
|
def _visit_body(self, body: StatementBlock) -> str:
|
349
355
|
code = ""
|
350
356
|
self._level += 1
|
@@ -390,6 +396,9 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
390
396
|
def visit_FieldHandleBinding(self, var_ref: FieldHandleBinding) -> str:
|
391
397
|
return f"{self.visit(var_ref.base_handle)}.{self.visit(var_ref.field)}"
|
392
398
|
|
399
|
+
def visit_HandlesList(self, handles: HandlesList) -> str:
|
400
|
+
return f"{{{', '.join(map(self.visit, handles.handles))}}}"
|
401
|
+
|
393
402
|
def visit_ArithmeticOperation(self, arith_op: ArithmeticOperation) -> str:
|
394
403
|
if arith_op.operation_kind == ArithmeticOperationKind.Assignment:
|
395
404
|
op = "="
|
@@ -37,6 +37,7 @@ from classiq.interface.model.control import Control
|
|
37
37
|
from classiq.interface.model.handle_binding import (
|
38
38
|
FieldHandleBinding,
|
39
39
|
HandleBinding,
|
40
|
+
HandlesList,
|
40
41
|
SlicedHandleBinding,
|
41
42
|
SubscriptHandleBinding,
|
42
43
|
)
|
@@ -264,7 +265,7 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
264
265
|
if port_decl.direction is not PortDeclarationDirection.Inout:
|
265
266
|
self._imports[port_decl.direction.name] = 1
|
266
267
|
var_type = f"{port_decl.direction.name}[{var_type}]"
|
267
|
-
if port_decl.type_qualifier
|
268
|
+
if port_decl.type_qualifier in [TypeQualifier.Const, TypeQualifier.QFree]:
|
268
269
|
self._imports[port_decl.type_qualifier.name] = 1
|
269
270
|
var_type = f"{port_decl.type_qualifier.name}[{var_type}]"
|
270
271
|
return var_type
|
@@ -518,6 +519,9 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
518
519
|
def visit_FieldHandleBinding(self, var_ref: FieldHandleBinding) -> str:
|
519
520
|
return f"{self.visit(var_ref.base_handle)}.{self.visit(var_ref.field)}"
|
520
521
|
|
522
|
+
def visit_HandlesList(self, handles: HandlesList) -> str:
|
523
|
+
return self.visit(handles.handles)
|
524
|
+
|
521
525
|
def visit_ArithmeticOperation(
|
522
526
|
self, arith_op: ArithmeticOperation, in_lambda: bool = False
|
523
527
|
) -> str:
|
@@ -19,7 +19,7 @@ from classiq.interface.generator.functions.classical_type import (
|
|
19
19
|
Real,
|
20
20
|
)
|
21
21
|
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
22
|
-
from classiq.interface.generator.functions.type_name import Enum, Struct
|
22
|
+
from classiq.interface.generator.functions.type_name import Enum, Struct, TypeName
|
23
23
|
|
24
24
|
from classiq.qmod.cparam import CArray, CBool, CInt, CReal
|
25
25
|
from classiq.qmod.utilities import version_portable_get_args
|
@@ -59,8 +59,7 @@ class PythonClassicalType:
|
|
59
59
|
)
|
60
60
|
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
61
61
|
elif inspect.isclass(py_type) and dataclasses.is_dataclass(py_type):
|
62
|
-
self.register_struct(py_type)
|
63
|
-
return Struct(name=py_type.__name__)
|
62
|
+
return self.register_struct(py_type)
|
64
63
|
elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
|
65
64
|
self.register_enum(py_type)
|
66
65
|
return Enum(name=py_type.__name__)
|
@@ -68,8 +67,8 @@ class PythonClassicalType:
|
|
68
67
|
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
69
68
|
return None
|
70
69
|
|
71
|
-
def register_struct(self, py_type: type) ->
|
72
|
-
|
70
|
+
def register_struct(self, py_type: type) -> TypeName:
|
71
|
+
return Struct(name=py_type.__name__)
|
73
72
|
|
74
73
|
def register_enum(self, py_type: EnumMeta) -> None:
|
75
74
|
pass
|
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_constant.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import inspect
|
2
2
|
from dataclasses import is_dataclass
|
3
|
-
from typing import Any, Optional, cast, get_origin
|
3
|
+
from typing import TYPE_CHECKING, Any, Optional, cast, get_origin
|
4
4
|
|
5
5
|
from classiq.interface.exceptions import ClassiqError, ClassiqValueError
|
6
6
|
from classiq.interface.generator.constant import Constant
|
@@ -17,7 +17,7 @@ from classiq.qmod.generative import (
|
|
17
17
|
interpret_expression,
|
18
18
|
is_generative_mode,
|
19
19
|
)
|
20
|
-
from classiq.qmod.model_state_container import ModelStateContainer
|
20
|
+
from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
|
21
21
|
from classiq.qmod.qmod_parameter import CParam, CParamList, CParamStruct
|
22
22
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
23
23
|
from classiq.qmod.utilities import qmod_val_to_expr_str
|
@@ -42,11 +42,12 @@ class QConstant(SymbolicExpr):
|
|
42
42
|
|
43
43
|
def add_to_model(self) -> None:
|
44
44
|
from classiq.qmod.builtins.constants import __all__ as builtin_constants
|
45
|
+
from classiq.qmod.semantics.validation.constants_validation import (
|
46
|
+
check_duplicate_constants,
|
47
|
+
)
|
45
48
|
|
46
|
-
if self.name in builtin_constants:
|
49
|
+
if self.name in builtin_constants or QConstant.CURRENT_QMODULE is None:
|
47
50
|
return
|
48
|
-
if QConstant.CURRENT_QMODULE is None:
|
49
|
-
raise ClassiqError(QMODULE_ERROR_MESSAGE)
|
50
51
|
|
51
52
|
expr = qmod_val_to_expr_str(self._value)
|
52
53
|
if (
|
@@ -57,6 +58,7 @@ class QConstant(SymbolicExpr):
|
|
57
58
|
|
58
59
|
constant = self._get_constant_node()
|
59
60
|
QConstant.CURRENT_QMODULE.constants[self.name] = constant
|
61
|
+
check_duplicate_constants([constant])
|
60
62
|
if is_generative_mode():
|
61
63
|
get_frontend_interpreter().add_constant(constant)
|
62
64
|
|
@@ -106,8 +108,10 @@ class QConstant(SymbolicExpr):
|
|
106
108
|
def __getitem__(self, item: Any) -> CParam:
|
107
109
|
self.add_to_model()
|
108
110
|
|
109
|
-
|
110
|
-
|
111
|
+
if QConstant.CURRENT_QMODULE is None:
|
112
|
+
QConstant.set_current_model(QMODULE)
|
113
|
+
if TYPE_CHECKING:
|
114
|
+
assert QConstant.CURRENT_QMODULE is not None
|
111
115
|
qmod_type = python_type_to_qmod(
|
112
116
|
self._py_type, qmodule=QConstant.CURRENT_QMODULE
|
113
117
|
)
|
@@ -141,3 +145,7 @@ class QConstant(SymbolicExpr):
|
|
141
145
|
if is_generative_mode():
|
142
146
|
return interpret_expression(len_expr)
|
143
147
|
return cast(int, CParamScalar(len_expr))
|
148
|
+
|
149
|
+
def __str__(self) -> str:
|
150
|
+
self.add_to_model()
|
151
|
+
return super().__str__()
|
classiq/qmod/qmod_variable.py
CHANGED
@@ -70,6 +70,8 @@ from classiq.qmod.generative import (
|
|
70
70
|
)
|
71
71
|
from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
|
72
72
|
from classiq.qmod.quantum_callable import QCallable
|
73
|
+
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
74
|
+
from classiq.qmod.semantics.validation.types_validation import validate_qstruct
|
73
75
|
from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
|
74
76
|
from classiq.qmod.symbolic_type import SymbolicTypes
|
75
77
|
from classiq.qmod.utilities import (
|
@@ -696,6 +698,8 @@ def _register_qstruct(
|
|
696
698
|
if type_hint is QStruct or struct_name in qmodule.qstruct_decls:
|
697
699
|
return
|
698
700
|
|
701
|
+
# temp assignment for recursive qstruct definitions
|
702
|
+
qmodule.qstruct_decls[struct_name] = QStructDeclaration(name=struct_name)
|
699
703
|
_validate_fields(type_hint)
|
700
704
|
struct_decl = QStructDeclaration(
|
701
705
|
name=struct_name,
|
@@ -705,6 +709,8 @@ def _register_qstruct(
|
|
705
709
|
},
|
706
710
|
)
|
707
711
|
qmodule.qstruct_decls[struct_name] = struct_decl
|
712
|
+
QStructAnnotator().visit(struct_decl)
|
713
|
+
validate_qstruct(struct_decl)
|
708
714
|
|
709
715
|
|
710
716
|
def _validate_fields(type_hint: type[QStruct]) -> None:
|
@@ -749,5 +755,5 @@ def _get_root_type(py_type: Any) -> type[QVar]:
|
|
749
755
|
)
|
750
756
|
root_type = get_origin(non_annotated_type) or non_annotated_type
|
751
757
|
if not issubclass(root_type, QVar):
|
752
|
-
raise
|
758
|
+
raise ClassiqValueError(f"Invalid quantum type {root_type.__name__!r}")
|
753
759
|
return root_type
|