classiq 0.74.0__py3-none-any.whl → 0.76.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 +8 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -4
- classiq/applications/qnn/gradients/quantum_gradient.py +3 -5
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -2
- classiq/applications/qnn/qlayer.py +23 -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 +18 -13
- 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 +46 -22
- classiq/interface/generator/expressions/proxies/classical/qmod_struct_instance.py +7 -0
- classiq/interface/generator/expressions/proxies/classical/utils.py +14 -13
- classiq/interface/generator/expressions/proxies/quantum/qmod_qscalar_proxy.py +9 -2
- classiq/interface/generator/expressions/proxies/quantum/qmod_sized_proxy.py +4 -1
- classiq/interface/generator/expressions/sympy_supported_expressions.py +1 -0
- classiq/interface/generator/functions/classical_type.py +36 -1
- classiq/interface/generator/functions/type_name.py +32 -5
- classiq/interface/generator/functions/type_qualifier.py +15 -0
- classiq/interface/generator/generated_circuit_data.py +11 -25
- classiq/interface/generator/model/preferences/preferences.py +7 -0
- classiq/interface/generator/quantum_program.py +5 -19
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +10 -13
- classiq/interface/helpers/backward_compatibility.py +9 -0
- classiq/interface/helpers/datastructures.py +6 -0
- classiq/interface/helpers/versioned_model.py +12 -0
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/handle_binding.py +12 -0
- classiq/interface/model/port_declaration.py +1 -2
- classiq/interface/model/quantum_lambda_function.py +2 -1
- classiq/interface/model/statement_block.py +9 -1
- classiq/interface/model/within_apply_operation.py +12 -0
- classiq/interface/server/routes.py +6 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +82 -23
- classiq/model_expansions/capturing/captured_vars.py +2 -0
- classiq/model_expansions/closure.py +18 -0
- classiq/model_expansions/evaluators/argument_types.py +6 -5
- classiq/model_expansions/evaluators/classical_type_inference.py +17 -6
- classiq/model_expansions/evaluators/parameter_types.py +26 -13
- classiq/model_expansions/evaluators/type_type_match.py +2 -2
- classiq/model_expansions/expression_evaluator.py +1 -1
- classiq/model_expansions/generative_functions.py +66 -33
- classiq/model_expansions/interpreters/base_interpreter.py +27 -19
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +26 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +25 -1
- classiq/model_expansions/quantum_operations/allocate.py +27 -11
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +220 -19
- 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 +14 -12
- 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 -8
- classiq/model_expansions/quantum_operations/expression_evaluator.py +1 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +1 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -3
- classiq/model_expansions/scope.py +10 -7
- 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 +48 -8
- classiq/model_expansions/utils/handles_collector.py +1 -1
- classiq/model_expansions/visitors/symbolic_param_inference.py +197 -0
- classiq/model_expansions/visitors/variable_references.py +45 -9
- 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/declaration_inferrer.py +19 -7
- classiq/qmod/generative.py +9 -1
- classiq/qmod/native/expression_to_qmod.py +4 -0
- classiq/qmod/native/pretty_printer.py +8 -3
- classiq/qmod/pretty_print/pretty_printer.py +1 -1
- classiq/qmod/python_classical_type.py +4 -5
- classiq/qmod/qmod_constant.py +15 -7
- classiq/qmod/qmod_variable.py +30 -2
- classiq/qmod/quantum_function.py +19 -6
- 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 +34 -2
- classiq/qmod/write_qmod.py +5 -1
- classiq/synthesis.py +17 -31
- classiq/visualization.py +35 -0
- {classiq-0.74.0.dist-info → classiq-0.76.0.dist-info}/METADATA +1 -1
- {classiq-0.74.0.dist-info → classiq-0.76.0.dist-info}/RECORD +96 -91
- {classiq-0.74.0.dist-info → classiq-0.76.0.dist-info}/WHEEL +1 -1
@@ -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
|
|
@@ -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
|
@@ -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,
|
@@ -192,7 +193,7 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
192
193
|
def visit_AnonPortDeclaration(self, port_decl: AnonPortDeclaration) -> str:
|
193
194
|
qualifier_str = (
|
194
195
|
f"{port_decl.type_qualifier} "
|
195
|
-
if port_decl.type_qualifier
|
196
|
+
if port_decl.type_qualifier in [TypeQualifier.Const, TypeQualifier.QFree]
|
196
197
|
else ""
|
197
198
|
)
|
198
199
|
dir_str = (
|
@@ -308,8 +309,6 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
308
309
|
|
309
310
|
def visit_ClassicalIf(self, op: ClassicalIf) -> str:
|
310
311
|
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
312
|
classical_if += self._visit_body(op.then)
|
314
313
|
|
315
314
|
if op.else_:
|
@@ -345,6 +344,12 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
345
344
|
invert_code += f"{self._indent}}}\n"
|
346
345
|
return invert_code
|
347
346
|
|
347
|
+
def visit_Block(self, block: Block) -> str:
|
348
|
+
invert_code = f"{self._indent}block {{\n"
|
349
|
+
invert_code += self._visit_body(block.statements)
|
350
|
+
invert_code += f"{self._indent}}}\n"
|
351
|
+
return invert_code
|
352
|
+
|
348
353
|
def _visit_body(self, body: StatementBlock) -> str:
|
349
354
|
code = ""
|
350
355
|
self._level += 1
|
@@ -264,7 +264,7 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
264
264
|
if port_decl.direction is not PortDeclarationDirection.Inout:
|
265
265
|
self._imports[port_decl.direction.name] = 1
|
266
266
|
var_type = f"{port_decl.direction.name}[{var_type}]"
|
267
|
-
if port_decl.type_qualifier
|
267
|
+
if port_decl.type_qualifier in [TypeQualifier.Const, TypeQualifier.QFree]:
|
268
268
|
self._imports[port_decl.type_qualifier.name] = 1
|
269
269
|
var_type = f"{port_decl.type_qualifier.name}[{var_type}]"
|
270
270
|
return var_type
|
@@ -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/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
@@ -22,7 +22,12 @@ from typing import ( # type: ignore[attr-defined]
|
|
22
22
|
|
23
23
|
from typing_extensions import ParamSpec, Self, _AnnotatedAlias
|
24
24
|
|
25
|
-
from classiq.interface.exceptions import
|
25
|
+
from classiq.interface.exceptions import (
|
26
|
+
ClassiqInternalError,
|
27
|
+
ClassiqNotImplementedError,
|
28
|
+
ClassiqValueError,
|
29
|
+
)
|
30
|
+
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
26
31
|
from classiq.interface.generator.expressions.expression import Expression
|
27
32
|
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
28
33
|
from classiq.interface.generator.expressions.proxies.quantum.qmod_qarray_proxy import (
|
@@ -65,6 +70,8 @@ from classiq.qmod.generative import (
|
|
65
70
|
)
|
66
71
|
from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
|
67
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
|
68
75
|
from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
|
69
76
|
from classiq.qmod.symbolic_type import SymbolicTypes
|
70
77
|
from classiq.qmod.utilities import (
|
@@ -340,6 +347,23 @@ class QNum(Generic[_P], QScalar):
|
|
340
347
|
return interpret_expression(str(self.is_signed))
|
341
348
|
return CParamScalar(f"get_field({self}, 'is_signed')")
|
342
349
|
|
350
|
+
def get_maximal_bounds(self) -> tuple[float, float]:
|
351
|
+
if not is_generative_mode():
|
352
|
+
raise ClassiqNotImplementedError(
|
353
|
+
"get_maximal_bounds() is supported in generative mode only"
|
354
|
+
)
|
355
|
+
|
356
|
+
if TYPE_CHECKING:
|
357
|
+
assert isinstance(self.size, int)
|
358
|
+
assert isinstance(self.is_signed, bool)
|
359
|
+
assert isinstance(self.fraction_digits, int)
|
360
|
+
|
361
|
+
return RegisterArithmeticInfo.get_maximal_bounds(
|
362
|
+
size=self.size,
|
363
|
+
is_signed=self.is_signed,
|
364
|
+
fraction_places=self.fraction_digits,
|
365
|
+
)
|
366
|
+
|
343
367
|
# Support comma-separated generic args in older Python versions
|
344
368
|
if sys.version_info[0:2] < (3, 10):
|
345
369
|
|
@@ -674,6 +698,8 @@ def _register_qstruct(
|
|
674
698
|
if type_hint is QStruct or struct_name in qmodule.qstruct_decls:
|
675
699
|
return
|
676
700
|
|
701
|
+
# temp assignment for recursive qstruct definitions
|
702
|
+
qmodule.qstruct_decls[struct_name] = QStructDeclaration(name=struct_name)
|
677
703
|
_validate_fields(type_hint)
|
678
704
|
struct_decl = QStructDeclaration(
|
679
705
|
name=struct_name,
|
@@ -683,6 +709,8 @@ def _register_qstruct(
|
|
683
709
|
},
|
684
710
|
)
|
685
711
|
qmodule.qstruct_decls[struct_name] = struct_decl
|
712
|
+
QStructAnnotator().visit(struct_decl)
|
713
|
+
validate_qstruct(struct_decl)
|
686
714
|
|
687
715
|
|
688
716
|
def _validate_fields(type_hint: type[QStruct]) -> None:
|
@@ -727,5 +755,5 @@ def _get_root_type(py_type: Any) -> type[QVar]:
|
|
727
755
|
)
|
728
756
|
root_type = get_origin(non_annotated_type) or non_annotated_type
|
729
757
|
if not issubclass(root_type, QVar):
|
730
|
-
raise
|
758
|
+
raise ClassiqValueError(f"Invalid quantum type {root_type.__name__!r}")
|
731
759
|
return root_type
|
classiq/qmod/quantum_function.py
CHANGED
@@ -14,7 +14,7 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
14
14
|
from classiq.interface.generator.model.constraints import Constraints
|
15
15
|
from classiq.interface.generator.model.preferences.preferences import Preferences
|
16
16
|
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
17
|
-
from classiq.interface.model.model import Model
|
17
|
+
from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model
|
18
18
|
from classiq.interface.model.native_function_definition import (
|
19
19
|
NativeFunctionDefinition,
|
20
20
|
)
|
@@ -31,6 +31,7 @@ from classiq.qmod.qmod_parameter import CArray
|
|
31
31
|
from classiq.qmod.quantum_callable import QCallable, QCallableList
|
32
32
|
from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
|
33
33
|
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
34
|
+
from classiq.qmod.semantics.validation.main_validation import validate_main_function
|
34
35
|
from classiq.qmod.utilities import mangle_keyword
|
35
36
|
|
36
37
|
|
@@ -104,7 +105,7 @@ class QFunc(BaseQFunc):
|
|
104
105
|
@property
|
105
106
|
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
106
107
|
name = self._py_callable.__name__
|
107
|
-
if
|
108
|
+
if name in self._qmodule.native_defs:
|
108
109
|
return self._qmodule.native_defs[name]
|
109
110
|
return infer_func_decl(self._py_callable, qmodule=self._qmodule)
|
110
111
|
|
@@ -250,15 +251,23 @@ class GenerativeQFunc(BaseQFunc):
|
|
250
251
|
) -> None:
|
251
252
|
super().__init__(py_callable, compilation_metadata)
|
252
253
|
self._func_decl = func_decl
|
254
|
+
self._inferred_func_decl: Optional[NamedParamsQuantumFunctionDeclaration] = None
|
253
255
|
|
254
256
|
@property
|
255
257
|
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
256
|
-
if self._func_decl is None:
|
257
|
-
self._func_decl
|
258
|
-
|
258
|
+
if self._func_decl is not None:
|
259
|
+
return self._func_decl
|
260
|
+
if self._inferred_func_decl is None:
|
261
|
+
self._inferred_func_decl = infer_func_decl(self._py_callable, self._qmodule)
|
262
|
+
return self._inferred_func_decl
|
259
263
|
|
260
264
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
261
|
-
self.
|
265
|
+
if self.func_decl.name not in self._qmodule.generative_functions:
|
266
|
+
self._qmodule.generative_functions[self.func_decl.name] = self
|
267
|
+
if self._func_decl is None:
|
268
|
+
self._inferred_func_decl = infer_func_decl(
|
269
|
+
self._py_callable, self._qmodule
|
270
|
+
)
|
262
271
|
super().__call__(*args, **kwargs)
|
263
272
|
|
264
273
|
def create_model(
|
@@ -268,6 +277,10 @@ class GenerativeQFunc(BaseQFunc):
|
|
268
277
|
preferences: Optional[Preferences] = None,
|
269
278
|
classical_execution_function: Optional[CFunc] = None,
|
270
279
|
) -> Model:
|
280
|
+
self._qmodule.reset()
|
281
|
+
if self.func_decl.name == MAIN_FUNCTION_NAME:
|
282
|
+
validate_main_function(self.func_decl)
|
283
|
+
|
271
284
|
def _dec_main(*args: Any, **kwargs: Any) -> None:
|
272
285
|
self(*args, **kwargs)
|
273
286
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
from classiq.interface.helpers.backward_compatibility import zip_strict
|
1
2
|
from classiq.interface.model.port_declaration import PortDeclaration
|
2
3
|
from classiq.interface.model.quantum_function_declaration import (
|
3
4
|
AnonQuantumOperandDeclaration,
|
@@ -14,8 +15,11 @@ def get_renamed_parameters(
|
|
14
15
|
renamed_parameters: list[str] = []
|
15
16
|
renamed_operands: dict[str, QuantumOperandDeclaration] = {}
|
16
17
|
renamed_ports: list[PortDeclaration] = []
|
17
|
-
for
|
18
|
-
|
18
|
+
for param, param_name in zip_strict(
|
19
|
+
lambda_func.func_decl.positional_arg_declarations,
|
20
|
+
lambda_func.pos_rename_params,
|
21
|
+
strict=False,
|
22
|
+
):
|
19
23
|
if isinstance(param, AnonClassicalParameterDeclaration):
|
20
24
|
renamed_parameters.append(param_name)
|
21
25
|
elif isinstance(param, AnonQuantumOperandDeclaration):
|
@@ -1,16 +1,22 @@
|
|
1
|
-
from classiq.interface.exceptions import ClassiqExpansionError
|
1
|
+
from classiq.interface.exceptions import ClassiqExpansionError, ClassiqValueError
|
2
2
|
from classiq.interface.generator.functions.classical_type import (
|
3
3
|
ClassicalArray,
|
4
4
|
ClassicalList,
|
5
5
|
)
|
6
6
|
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
7
|
-
from classiq.interface.
|
8
|
-
|
7
|
+
from classiq.interface.generator.functions.port_declaration import (
|
8
|
+
PortDeclarationDirection,
|
9
|
+
)
|
10
|
+
from classiq.interface.model.port_declaration import PortDeclaration
|
11
|
+
from classiq.interface.model.quantum_function_declaration import (
|
12
|
+
NamedParamsQuantumFunctionDeclaration,
|
13
|
+
PositionalArg,
|
14
|
+
)
|
9
15
|
|
10
16
|
from classiq import ClassicalParameterDeclaration
|
11
17
|
|
12
18
|
|
13
|
-
def validate_main_function(func:
|
19
|
+
def validate_main_function(func: NamedParamsQuantumFunctionDeclaration) -> None:
|
14
20
|
for param in func.positional_arg_declarations:
|
15
21
|
_validate_main_param(param)
|
16
22
|
|
@@ -18,6 +24,8 @@ def validate_main_function(func: NativeFunctionDefinition) -> None:
|
|
18
24
|
def _validate_main_param(param: PositionalArg) -> None:
|
19
25
|
if isinstance(param, ClassicalParameterDeclaration):
|
20
26
|
_validate_main_classical_param_type(param.classical_type, param.name)
|
27
|
+
if isinstance(param, PortDeclaration):
|
28
|
+
_validate_main_quantum_param_type(param)
|
21
29
|
|
22
30
|
|
23
31
|
def _validate_main_classical_param_type(
|
@@ -30,3 +38,8 @@ def _validate_main_classical_param_type(
|
|
30
38
|
)
|
31
39
|
if isinstance(param, ClassicalArray):
|
32
40
|
_validate_main_classical_param_type(param.element_type, param_name)
|
41
|
+
|
42
|
+
|
43
|
+
def _validate_main_quantum_param_type(param: PortDeclaration) -> None:
|
44
|
+
if param.direction != PortDeclarationDirection.Output:
|
45
|
+
raise ClassiqValueError("Function 'main' cannot declare quantum inputs")
|
classiq/qmod/symbolic.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import sys
|
2
|
-
from collections.abc import Sequence
|
3
2
|
from typing import (
|
4
3
|
TYPE_CHECKING,
|
5
4
|
Any,
|
@@ -12,6 +11,9 @@ from typing import (
|
|
12
11
|
import numpy as np
|
13
12
|
|
14
13
|
from classiq.interface.exceptions import ClassiqValueError
|
14
|
+
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
15
|
+
subscript_to_str,
|
16
|
+
)
|
15
17
|
|
16
18
|
from classiq.qmod import model_state_container
|
17
19
|
from classiq.qmod.declaration_inferrer import python_type_to_qmod
|
@@ -24,6 +26,7 @@ from classiq.qmod.qmod_parameter import (
|
|
24
26
|
)
|
25
27
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
26
28
|
from classiq.qmod.symbolic_type import SymbolicTypes
|
29
|
+
from classiq.qmod.utilities import qmod_val_to_expr_str
|
27
30
|
|
28
31
|
pi = SymbolicExpr("pi", False)
|
29
32
|
E = SymbolicExpr("E", False)
|
@@ -306,27 +309,13 @@ def sum(arr: SymbolicTypes) -> CParamScalar:
|
|
306
309
|
return symbolic_function(arr)
|
307
310
|
|
308
311
|
|
309
|
-
def _subscript_to_str(index: Any) -> str:
|
310
|
-
if not isinstance(index, slice):
|
311
|
-
return str(index)
|
312
|
-
expr = ""
|
313
|
-
if index.start is not None:
|
314
|
-
expr += str(index.start)
|
315
|
-
expr += ":"
|
316
|
-
if index.stop is not None:
|
317
|
-
expr += str(index.stop)
|
318
|
-
if index.step is not None:
|
319
|
-
expr += f":{index.step}"
|
320
|
-
return expr
|
321
|
-
|
322
|
-
|
323
312
|
def subscript(
|
324
|
-
array: Union[
|
325
|
-
Sequence[Union[float, CReal, CParamScalar]], CArray[CReal], np.ndarray
|
326
|
-
],
|
313
|
+
array: Union[list, CArray[CReal], np.ndarray],
|
327
314
|
index: Any,
|
328
315
|
) -> CParamScalar:
|
329
|
-
return CParamScalar(
|
316
|
+
return CParamScalar(
|
317
|
+
expr=f"{qmod_val_to_expr_str(_unwrap_numpy(array))}[{subscript_to_str(index)}]"
|
318
|
+
)
|
330
319
|
|
331
320
|
|
332
321
|
__all__ = [
|