classiq 0.93.0__py3-none-any.whl → 0.94.1__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.
Potentially problematic release.
This version of classiq might be problematic. Click here for more details.
- classiq/__init__.py +6 -19
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +7 -7
- classiq/_analyzer_extras/interactive_hardware.py +19 -12
- classiq/_internals/api_wrapper.py +38 -52
- classiq/_internals/async_utils.py +4 -7
- classiq/_internals/authentication/auth0.py +3 -3
- classiq/_internals/authentication/device.py +4 -4
- classiq/_internals/authentication/password_manager.py +13 -13
- classiq/_internals/authentication/token_manager.py +4 -5
- classiq/_internals/client.py +17 -44
- classiq/_internals/config.py +1 -2
- classiq/_internals/help.py +1 -2
- classiq/_internals/host_checker.py +3 -3
- classiq/_internals/jobs.py +14 -14
- classiq/_internals/type_validation.py +3 -3
- classiq/analyzer/analyzer.py +18 -18
- classiq/analyzer/rb.py +17 -8
- classiq/applications/chemistry/__init__.py +0 -30
- classiq/applications/chemistry/op_utils.py +4 -4
- classiq/applications/chemistry/problems.py +3 -3
- classiq/applications/chemistry/ucc.py +1 -2
- classiq/applications/chemistry/z2_symmetries.py +4 -4
- classiq/applications/combinatorial_helpers/allowed_constraints.py +1 -3
- classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +2 -1
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +2 -2
- classiq/applications/combinatorial_helpers/encoding_mapping.py +2 -3
- classiq/applications/combinatorial_helpers/encoding_utils.py +2 -2
- classiq/applications/combinatorial_helpers/optimization_model.py +3 -4
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +2 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +8 -8
- classiq/applications/combinatorial_helpers/sympy_utils.py +1 -3
- classiq/applications/combinatorial_helpers/transformations/encoding.py +3 -3
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +1 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -3
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +4 -6
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +15 -10
- classiq/applications/hamiltonian/pauli_decomposition.py +6 -4
- classiq/applications/iqae/iqae.py +8 -8
- classiq/applications/qnn/datasets/dataset_base_classes.py +6 -6
- classiq/applications/qnn/datasets/dataset_parity.py +6 -6
- classiq/applications/qnn/qlayer.py +8 -7
- classiq/applications/qnn/torch_utils.py +3 -4
- classiq/applications/qnn/types.py +2 -1
- classiq/applications/qsp/qsp.py +5 -4
- classiq/applications/qsvm/qsvm_data_generation.py +1 -2
- classiq/evaluators/classical_expression.py +0 -4
- classiq/evaluators/parameter_types.py +7 -8
- classiq/evaluators/qmod_annotated_expression.py +24 -26
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +14 -14
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +2 -1
- classiq/evaluators/qmod_expression_visitors/sympy_wrappers.py +8 -8
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +4 -4
- classiq/evaluators/qmod_node_evaluators/list_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +3 -3
- classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +9 -9
- classiq/evaluators/qmod_node_evaluators/utils.py +6 -6
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +9 -10
- classiq/evaluators/qmod_type_inference/quantum_type_inference.py +5 -5
- classiq/execution/execution_session.py +18 -19
- classiq/execution/jobs.py +26 -26
- classiq/execution/qnn.py +1 -2
- classiq/execution/user_budgets.py +52 -7
- classiq/executor.py +1 -3
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +4 -4
- classiq/interface/analyzer/cytoscape_graph.py +3 -3
- classiq/interface/analyzer/result.py +4 -4
- classiq/interface/applications/qsvm.py +5 -8
- classiq/interface/ast_node.py +3 -3
- classiq/interface/backend/backend_preferences.py +16 -16
- classiq/interface/backend/ionq/ionq_quantum_program.py +5 -5
- classiq/interface/chemistry/ansatz_library.py +3 -5
- classiq/interface/chemistry/operator.py +3 -3
- classiq/interface/combinatorial_optimization/examples/knapsack.py +2 -4
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +1 -2
- classiq/interface/compression_utils.py +2 -3
- classiq/interface/debug_info/debug_info.py +7 -7
- classiq/interface/exceptions.py +2 -3
- classiq/interface/execution/iqcc.py +1 -3
- classiq/interface/execution/primitives.py +6 -6
- classiq/interface/executor/estimate_cost.py +1 -1
- classiq/interface/executor/execution_preferences.py +3 -5
- classiq/interface/executor/execution_request.py +10 -10
- classiq/interface/executor/execution_result.py +1 -2
- classiq/interface/executor/quantum_code.py +8 -8
- classiq/interface/executor/result.py +28 -18
- classiq/interface/executor/user_budget.py +2 -3
- classiq/interface/executor/vqe_result.py +5 -6
- classiq/interface/generator/ansatz_library.py +6 -8
- classiq/interface/generator/application_apis/__init__.py +0 -2
- classiq/interface/generator/arith/arithmetic.py +2 -2
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +2 -3
- classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -5
- classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -4
- classiq/interface/generator/arith/arithmetic_expression_validator.py +12 -15
- classiq/interface/generator/arith/arithmetic_operations.py +4 -6
- classiq/interface/generator/arith/arithmetic_param_getters.py +70 -107
- classiq/interface/generator/arith/arithmetic_result_builder.py +4 -4
- classiq/interface/generator/arith/ast_node_rewrite.py +8 -4
- classiq/interface/generator/arith/binary_ops.py +7 -36
- classiq/interface/generator/arith/logical_ops.py +2 -3
- classiq/interface/generator/arith/number_utils.py +2 -2
- classiq/interface/generator/arith/register_user_input.py +2 -2
- classiq/interface/generator/arith/unary_ops.py +2 -2
- classiq/interface/generator/circuit_code/circuit_code.py +8 -10
- classiq/interface/generator/circuit_code/types_and_constants.py +1 -1
- classiq/interface/generator/complex_type.py +2 -2
- classiq/interface/generator/copy.py +1 -3
- classiq/interface/generator/expressions/atomic_expression_functions.py +0 -5
- classiq/interface/generator/expressions/evaluated_expression.py +2 -3
- classiq/interface/generator/expressions/expression.py +2 -2
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -7
- classiq/interface/generator/function_param_list.py +0 -20
- classiq/interface/generator/function_params.py +5 -6
- classiq/interface/generator/functions/classical_function_declaration.py +2 -2
- classiq/interface/generator/functions/classical_type.py +3 -3
- classiq/interface/generator/functions/type_modifier.py +0 -14
- classiq/interface/generator/functions/type_name.py +2 -2
- classiq/interface/generator/generated_circuit_data.py +12 -13
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +2 -4
- classiq/interface/generator/hardware/hardware_data.py +8 -8
- classiq/interface/generator/hardware_efficient_ansatz.py +8 -8
- classiq/interface/generator/mcu.py +3 -3
- classiq/interface/generator/mcx.py +3 -3
- classiq/interface/generator/model/constraints.py +34 -5
- classiq/interface/generator/model/preferences/preferences.py +15 -21
- classiq/interface/generator/model/quantum_register.py +7 -10
- classiq/interface/generator/noise_properties.py +3 -7
- classiq/interface/generator/parameters.py +1 -1
- classiq/interface/generator/partitioned_register.py +1 -2
- classiq/interface/generator/preferences/qasm_to_qmod_params.py +11 -0
- classiq/interface/generator/qsvm.py +2 -2
- classiq/interface/generator/quantum_function_call.py +8 -11
- classiq/interface/generator/quantum_program.py +12 -15
- classiq/interface/generator/range_types.py +3 -3
- classiq/interface/generator/slice_parsing_utils.py +4 -5
- classiq/interface/generator/standard_gates/standard_gates.py +2 -4
- classiq/interface/generator/state_preparation/state_preparation.py +6 -8
- classiq/interface/generator/synthesis_execution_parameter.py +1 -3
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +2 -3
- classiq/interface/generator/transpiler_basis_gates.py +2 -4
- classiq/interface/generator/types/builtin_enum_declarations.py +0 -136
- classiq/interface/generator/types/compilation_metadata.py +12 -1
- classiq/interface/generator/types/enum_declaration.py +2 -1
- classiq/interface/generator/validations/flow_graph.py +3 -3
- classiq/interface/generator/visitor.py +10 -12
- classiq/interface/hardware.py +2 -2
- classiq/interface/helpers/classproperty.py +2 -2
- classiq/interface/helpers/custom_encoders.py +2 -1
- classiq/interface/helpers/custom_pydantic_types.py +1 -1
- classiq/interface/helpers/text_utils.py +1 -4
- classiq/interface/ide/visual_model.py +5 -5
- classiq/interface/jobs.py +3 -3
- classiq/interface/model/allocate.py +4 -4
- classiq/interface/model/block.py +2 -2
- classiq/interface/model/bounds.py +3 -3
- classiq/interface/model/control.py +1 -1
- classiq/interface/model/inplace_binary_operation.py +2 -2
- classiq/interface/model/model.py +4 -4
- classiq/interface/model/parameter.py +1 -3
- classiq/interface/model/port_declaration.py +1 -1
- classiq/interface/model/quantum_expressions/quantum_expression.py +1 -2
- classiq/interface/model/quantum_function_call.py +3 -6
- classiq/interface/model/quantum_function_declaration.py +1 -0
- classiq/interface/model/quantum_lambda_function.py +4 -4
- classiq/interface/model/quantum_statement.py +4 -4
- classiq/interface/model/quantum_type.py +14 -14
- classiq/interface/model/validation_handle.py +2 -3
- classiq/interface/model/variable_declaration_statement.py +2 -2
- classiq/interface/pretty_print/expression_to_qmod.py +3 -4
- classiq/interface/server/routes.py +0 -4
- classiq/interface/source_reference.py +3 -4
- classiq/model_expansions/arithmetic.py +6 -7
- classiq/model_expansions/arithmetic_compute_result_attrs.py +4 -5
- classiq/model_expansions/capturing/captured_vars.py +3 -3
- classiq/model_expansions/capturing/mangling_utils.py +1 -2
- classiq/model_expansions/closure.py +12 -11
- classiq/model_expansions/function_builder.py +14 -6
- classiq/model_expansions/generative_functions.py +1 -4
- classiq/model_expansions/interpreters/base_interpreter.py +2 -6
- classiq/model_expansions/interpreters/generative_interpreter.py +5 -3
- classiq/model_expansions/quantum_operations/allocate.py +4 -4
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +2 -4
- classiq/model_expansions/quantum_operations/call_emitter.py +31 -37
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +2 -2
- classiq/model_expansions/quantum_operations/emitter.py +3 -5
- classiq/model_expansions/quantum_operations/expression_evaluator.py +3 -3
- classiq/model_expansions/quantum_operations/skip_control_verifier.py +1 -2
- classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
- classiq/model_expansions/scope.py +7 -7
- classiq/model_expansions/scope_initialization.py +4 -0
- classiq/model_expansions/visitors/symbolic_param_inference.py +3 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +317 -0
- classiq/model_expansions/visitors/variable_references.py +15 -14
- classiq/open_library/functions/__init__.py +6 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
- classiq/open_library/functions/grover.py +8 -10
- classiq/open_library/functions/modular_exponentiation.py +96 -8
- classiq/qmod/__init__.py +5 -2
- classiq/qmod/builtins/classical_execution_primitives.py +4 -11
- classiq/qmod/builtins/classical_functions.py +1 -42
- classiq/qmod/builtins/enums.py +0 -136
- classiq/qmod/builtins/functions/__init__.py +0 -13
- classiq/qmod/builtins/functions/allocation.py +4 -4
- classiq/qmod/builtins/functions/arithmetic.py +22 -27
- classiq/qmod/builtins/functions/standard_gates.py +27 -27
- classiq/qmod/builtins/operations.py +35 -58
- classiq/qmod/builtins/structs.py +2 -58
- classiq/qmod/cfunc.py +3 -2
- classiq/qmod/classical_function.py +2 -1
- classiq/qmod/cparam.py +2 -8
- classiq/qmod/create_model_function.py +7 -7
- classiq/qmod/declaration_inferrer.py +33 -30
- classiq/qmod/model_state_container.py +2 -2
- classiq/qmod/native/pretty_printer.py +25 -14
- classiq/qmod/pretty_print/expression_to_python.py +5 -3
- classiq/qmod/pretty_print/pretty_printer.py +39 -17
- classiq/qmod/python_classical_type.py +40 -13
- classiq/qmod/qfunc.py +139 -16
- classiq/qmod/qmod_constant.py +2 -2
- classiq/qmod/qmod_parameter.py +5 -2
- classiq/qmod/qmod_variable.py +47 -43
- classiq/qmod/quantum_callable.py +18 -13
- classiq/qmod/quantum_expandable.py +31 -26
- classiq/qmod/quantum_function.py +51 -32
- classiq/qmod/semantics/annotation/call_annotation.py +2 -2
- classiq/qmod/semantics/error_manager.py +5 -6
- classiq/qmod/semantics/lambdas.py +1 -2
- classiq/qmod/semantics/validation/types_validation.py +1 -2
- classiq/qmod/symbolic.py +2 -4
- classiq/qmod/utilities.py +13 -10
- classiq/qmod/write_qmod.py +3 -4
- classiq/quantum_program.py +1 -3
- classiq/synthesis.py +11 -7
- {classiq-0.93.0.dist-info → classiq-0.94.1.dist-info}/METADATA +2 -3
- {classiq-0.93.0.dist-info → classiq-0.94.1.dist-info}/RECORD +238 -260
- classiq/applications/chemistry/ansatz_parameters.py +0 -29
- classiq/applications/chemistry/chemistry_execution_parameters.py +0 -16
- classiq/applications/chemistry/chemistry_model_constructor.py +0 -532
- classiq/applications/chemistry/ground_state_problem.py +0 -42
- classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -129
- classiq/interface/chemistry/elements.py +0 -120
- classiq/interface/chemistry/fermionic_operator.py +0 -208
- classiq/interface/chemistry/ground_state_problem.py +0 -132
- classiq/interface/chemistry/ground_state_result.py +0 -8
- classiq/interface/chemistry/molecule.py +0 -71
- classiq/interface/generator/application_apis/chemistry_declarations.py +0 -69
- classiq/interface/generator/application_apis/entangler_declarations.py +0 -29
- classiq/interface/generator/chemistry_function_params.py +0 -50
- classiq/interface/generator/entangler_params.py +0 -72
- classiq/interface/generator/entanglers.py +0 -14
- classiq/interface/generator/hartree_fock.py +0 -26
- classiq/interface/generator/hva.py +0 -22
- classiq/interface/generator/linear_pauli_rotations.py +0 -92
- classiq/interface/generator/qft.py +0 -37
- classiq/interface/generator/ucc.py +0 -74
- classiq/interface/helpers/backward_compatibility.py +0 -9
- classiq/model_expansions/transformers/type_modifier_inference.py +0 -392
- classiq/qmod/builtins/functions/chemistry.py +0 -123
- {classiq-0.93.0.dist-info → classiq-0.94.1.dist-info}/WHEEL +0 -0
- {classiq-0.93.0.dist-info → classiq-0.94.1.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import dataclasses
|
|
2
|
-
import
|
|
3
|
-
from collections.abc import Sequence
|
|
2
|
+
from collections.abc import Callable, Sequence
|
|
4
3
|
from enum import EnumMeta
|
|
5
4
|
from typing import (
|
|
5
|
+
Annotated,
|
|
6
6
|
Any,
|
|
7
|
-
Callable,
|
|
8
7
|
Literal,
|
|
9
|
-
Optional,
|
|
10
8
|
get_args,
|
|
11
9
|
get_origin,
|
|
12
10
|
overload,
|
|
@@ -39,21 +37,22 @@ from classiq.qmod.builtins.structs import BUILTIN_STRUCT_DECLARATIONS
|
|
|
39
37
|
from classiq.qmod.model_state_container import ModelStateContainer
|
|
40
38
|
from classiq.qmod.python_classical_type import PythonClassicalType
|
|
41
39
|
from classiq.qmod.qmod_variable import QVar, get_port_from_type_hint
|
|
42
|
-
from classiq.qmod.quantum_callable import QCallableList
|
|
40
|
+
from classiq.qmod.quantum_callable import QCallable, QCallableList, QPerm, QPermList
|
|
43
41
|
from classiq.qmod.semantics.annotation.qstruct_annotator import QStructAnnotator
|
|
44
42
|
from classiq.qmod.semantics.validation.type_hints import validate_annotation
|
|
45
43
|
from classiq.qmod.semantics.validation.types_validation import (
|
|
46
44
|
check_duplicate_types,
|
|
47
45
|
validate_cstruct,
|
|
48
46
|
)
|
|
49
|
-
from classiq.qmod.utilities import
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
from classiq.qmod.utilities import (
|
|
48
|
+
type_to_str,
|
|
49
|
+
unmangle_keyword,
|
|
50
|
+
version_portable_get_args,
|
|
51
|
+
)
|
|
53
52
|
|
|
54
53
|
|
|
55
54
|
class _PythonClassicalType(PythonClassicalType):
|
|
56
|
-
def __init__(self, qmodule:
|
|
55
|
+
def __init__(self, qmodule: ModelStateContainer | None):
|
|
57
56
|
super().__init__()
|
|
58
57
|
self.qmodule = qmodule
|
|
59
58
|
|
|
@@ -97,12 +96,12 @@ class _PythonClassicalType(PythonClassicalType):
|
|
|
97
96
|
|
|
98
97
|
|
|
99
98
|
def python_type_to_qmod(
|
|
100
|
-
py_type: type, *, qmodule:
|
|
101
|
-
) ->
|
|
99
|
+
py_type: type, *, qmodule: ModelStateContainer | None
|
|
100
|
+
) -> ConcreteClassicalType | None:
|
|
102
101
|
return _PythonClassicalType(qmodule).convert(py_type)
|
|
103
102
|
|
|
104
103
|
|
|
105
|
-
def _extract_port_decl(name:
|
|
104
|
+
def _extract_port_decl(name: str | None, py_type: Any) -> AnonPortDeclaration:
|
|
106
105
|
quantum_type, direction, modifier = get_port_from_type_hint(py_type)
|
|
107
106
|
param = AnonPortDeclaration(
|
|
108
107
|
name=None,
|
|
@@ -116,33 +115,30 @@ def _extract_port_decl(name: Optional[str], py_type: Any) -> AnonPortDeclaration
|
|
|
116
115
|
|
|
117
116
|
|
|
118
117
|
def _extract_operand_decl(
|
|
119
|
-
name:
|
|
118
|
+
name: str | None, py_type: Any, qmodule: ModelStateContainer | None
|
|
120
119
|
) -> AnonQuantumOperandDeclaration:
|
|
121
|
-
is_list = (get_origin(py_type) or py_type) is QCallableList
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
is_list = (get_origin(py_type) or py_type) is QCallableList or (
|
|
121
|
+
get_origin(py_type) or py_type
|
|
122
|
+
) is QPermList
|
|
123
|
+
is_permutation = (get_origin(py_type) or py_type) is QPerm or (
|
|
124
|
+
get_origin(py_type) or py_type
|
|
125
|
+
) is QPermList
|
|
127
126
|
type_args = version_portable_get_args(py_type)
|
|
128
|
-
if len(type_args) > 0 and isinstance(type_args[0], list): # Callable support
|
|
129
|
-
type_args = tuple(type_args[0])
|
|
130
127
|
param_decls = [_extract_operand_param(arg_type) for arg_type in type_args]
|
|
131
128
|
param = AnonQuantumOperandDeclaration(
|
|
132
129
|
name=name,
|
|
133
130
|
positional_arg_declarations=_extract_positional_args(
|
|
134
131
|
param_decls, qmodule=qmodule
|
|
135
132
|
),
|
|
133
|
+
permutation=is_permutation,
|
|
136
134
|
is_list=is_list,
|
|
137
135
|
)
|
|
138
|
-
if is_generative:
|
|
139
|
-
param = param.set_generative()
|
|
140
136
|
if name is not None:
|
|
141
137
|
param = param.rename(name)
|
|
142
138
|
return param
|
|
143
139
|
|
|
144
140
|
|
|
145
|
-
def _extract_operand_param(py_type: Any) -> tuple[
|
|
141
|
+
def _extract_operand_param(py_type: Any) -> tuple[str | None, Any]:
|
|
146
142
|
if get_origin(py_type) is not Annotated:
|
|
147
143
|
return None, py_type
|
|
148
144
|
|
|
@@ -164,7 +160,7 @@ def _unpacked_annotated(arg_0: Any, args: Any) -> _AnnotatedAlias:
|
|
|
164
160
|
return Annotated.__class_getitem__((arg_0, *args)) # type:ignore[attr-defined]
|
|
165
161
|
|
|
166
162
|
|
|
167
|
-
def _get_param_name(py_type_args: Any) ->
|
|
163
|
+
def _get_param_name(py_type_args: Any) -> str | None:
|
|
168
164
|
if isinstance(py_type_args[-1], str) and not isinstance(
|
|
169
165
|
py_type_args[-1], (PortDeclarationDirection, TypeModifier)
|
|
170
166
|
):
|
|
@@ -189,20 +185,20 @@ def _validate_annotations(py_type_args: Any, py_type: Any) -> None:
|
|
|
189
185
|
|
|
190
186
|
@overload
|
|
191
187
|
def _extract_positional_args(
|
|
192
|
-
args: Sequence[tuple[str, Any]], qmodule:
|
|
188
|
+
args: Sequence[tuple[str, Any]], qmodule: ModelStateContainer | None
|
|
193
189
|
) -> Sequence[PositionalArg]:
|
|
194
190
|
pass
|
|
195
191
|
|
|
196
192
|
|
|
197
193
|
@overload
|
|
198
194
|
def _extract_positional_args(
|
|
199
|
-
args: Sequence[tuple[
|
|
195
|
+
args: Sequence[tuple[str | None, Any]], qmodule: ModelStateContainer | None
|
|
200
196
|
) -> Sequence[AnonPositionalArg]:
|
|
201
197
|
pass
|
|
202
198
|
|
|
203
199
|
|
|
204
200
|
def _extract_positional_args(
|
|
205
|
-
args: Sequence[tuple[
|
|
201
|
+
args: Sequence[tuple[str | None, Any]], qmodule: ModelStateContainer | None
|
|
206
202
|
) -> Sequence[AnonPositionalArg]:
|
|
207
203
|
result: list[AnonPositionalArg] = []
|
|
208
204
|
for name, py_type in args:
|
|
@@ -222,18 +218,25 @@ def _extract_positional_args(
|
|
|
222
218
|
elif is_qvar(py_type):
|
|
223
219
|
result.append(_extract_port_decl(name, py_type))
|
|
224
220
|
else:
|
|
221
|
+
if not issubclass(get_origin(py_type) or py_type, QCallable):
|
|
222
|
+
raise ClassiqValueError(
|
|
223
|
+
f"Unsupported type annotation {type_to_str(py_type)!r}"
|
|
224
|
+
)
|
|
225
225
|
result.append(_extract_operand_decl(name, py_type, qmodule=qmodule))
|
|
226
226
|
return result
|
|
227
227
|
|
|
228
228
|
|
|
229
229
|
def infer_func_decl(
|
|
230
|
-
py_func: Callable,
|
|
230
|
+
py_func: Callable,
|
|
231
|
+
qmodule: ModelStateContainer | None = None,
|
|
232
|
+
permutation: bool = False,
|
|
231
233
|
) -> NamedParamsQuantumFunctionDeclaration:
|
|
232
234
|
return NamedParamsQuantumFunctionDeclaration(
|
|
233
235
|
name=unmangle_keyword(py_func.__name__),
|
|
234
236
|
positional_arg_declarations=_extract_positional_args(
|
|
235
237
|
list(py_func.__annotations__.items()), qmodule=qmodule
|
|
236
238
|
),
|
|
239
|
+
permutation=permutation,
|
|
237
240
|
)
|
|
238
241
|
|
|
239
242
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections import defaultdict
|
|
2
2
|
from collections.abc import Sequence
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from classiq.interface.generator.constant import Constant
|
|
6
6
|
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
|
@@ -40,7 +40,7 @@ class ModelStateContainer:
|
|
|
40
40
|
|
|
41
41
|
def user_types(
|
|
42
42
|
self,
|
|
43
|
-
) -> Sequence[
|
|
43
|
+
) -> Sequence[EnumDeclaration | StructDeclaration | QStructDeclaration]:
|
|
44
44
|
type_decls = [
|
|
45
45
|
t
|
|
46
46
|
for t in self.type_decls.values()
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from collections.abc import Mapping
|
|
2
|
-
from typing import Optional, Union
|
|
3
2
|
|
|
4
3
|
from classiq.interface.constants import DEFAULT_DECIMAL_PRECISION
|
|
5
4
|
from classiq.interface.exceptions import ClassiqInternalError
|
|
@@ -93,9 +92,9 @@ from classiq.qmod.semantics.annotation.call_annotation import resolve_function_c
|
|
|
93
92
|
class DSLPrettyPrinter(ModelVisitor):
|
|
94
93
|
def __init__(
|
|
95
94
|
self,
|
|
96
|
-
decimal_precision:
|
|
95
|
+
decimal_precision: int | None = DEFAULT_DECIMAL_PRECISION,
|
|
97
96
|
emit_open_lib_functions: bool = False,
|
|
98
|
-
compilation_metadata:
|
|
97
|
+
compilation_metadata: dict[str, CompilationMetadata] | None = None,
|
|
99
98
|
) -> None:
|
|
100
99
|
self._level = 0
|
|
101
100
|
self._decimal_precision = decimal_precision
|
|
@@ -145,19 +144,30 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
145
144
|
)
|
|
146
145
|
return f"({positional_args})"
|
|
147
146
|
|
|
148
|
-
def
|
|
149
|
-
if
|
|
147
|
+
def _get_decorators(self, func: str) -> str:
|
|
148
|
+
if func not in self._compilation_metadata:
|
|
150
149
|
return ""
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
150
|
+
|
|
151
|
+
decorators = ""
|
|
152
|
+
metadata = self._compilation_metadata[func]
|
|
153
|
+
|
|
154
|
+
if metadata.disable_perm_check:
|
|
155
|
+
decorators += "@disable_perm_check\n"
|
|
156
|
+
|
|
157
|
+
if metadata.disable_const_checks:
|
|
158
|
+
if metadata.disable_const_checks is True:
|
|
159
|
+
decorators += "@disable_const_checks\n"
|
|
160
|
+
else:
|
|
161
|
+
decorators += f"@disable_const_checks({', '.join(metadata.disable_const_checks)})\n"
|
|
162
|
+
|
|
163
|
+
return decorators
|
|
155
164
|
|
|
156
165
|
def visit_QuantumFunctionDeclaration(
|
|
157
166
|
self, func_decl: QuantumFunctionDeclaration
|
|
158
167
|
) -> str:
|
|
159
|
-
|
|
160
|
-
|
|
168
|
+
decorators = self._get_decorators(func_decl.name)
|
|
169
|
+
function_type = "qperm" if func_decl.permutation else "qfunc"
|
|
170
|
+
return f"{decorators}{function_type} {func_decl.name}{self._visit_arg_decls(func_decl)}"
|
|
161
171
|
|
|
162
172
|
def visit_EnumDeclaration(self, enum_decl: EnumDeclaration) -> str:
|
|
163
173
|
return f"enum {enum_decl.name} {{\n{self._visit_members(enum_decl.members)}}}\n"
|
|
@@ -178,7 +188,7 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
178
188
|
return f"qstruct {qstruct_decl.name} {{\n{self._visit_variables(qstruct_decl.fields)}}}\n"
|
|
179
189
|
|
|
180
190
|
def _visit_variables(
|
|
181
|
-
self, variables: Mapping[str,
|
|
191
|
+
self, variables: Mapping[str, ConcreteClassicalType | ConcreteQuantumType]
|
|
182
192
|
) -> str:
|
|
183
193
|
self._level += 1
|
|
184
194
|
variables_str = "".join(
|
|
@@ -191,7 +201,7 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
191
201
|
def visit_AnonPortDeclaration(self, port_decl: AnonPortDeclaration) -> str:
|
|
192
202
|
modifier_str = (
|
|
193
203
|
f"{port_decl.type_modifier} "
|
|
194
|
-
if port_decl.type_modifier
|
|
204
|
+
if port_decl.type_modifier is TypeModifier.Const
|
|
195
205
|
else ""
|
|
196
206
|
)
|
|
197
207
|
dir_str = (
|
|
@@ -265,7 +275,8 @@ class DSLPrettyPrinter(ModelVisitor):
|
|
|
265
275
|
self, op_decl: AnonQuantumOperandDeclaration
|
|
266
276
|
) -> str:
|
|
267
277
|
param_name = f"{op_decl.name}: " if op_decl.name is not None else ""
|
|
268
|
-
|
|
278
|
+
function_type = "qperm" if op_decl.permutation else "qfunc"
|
|
279
|
+
return f"{param_name}{function_type}{[] if op_decl.is_list else ''} {self._visit_arg_decls(op_decl)}"
|
|
269
280
|
|
|
270
281
|
def visit_QuantumOperandDeclaration(
|
|
271
282
|
self, op_decl: QuantumOperandDeclaration
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import ast
|
|
2
2
|
import re
|
|
3
|
-
from collections.abc import Mapping
|
|
3
|
+
from collections.abc import Callable, Mapping
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import Callable
|
|
6
5
|
|
|
7
6
|
import numpy as np
|
|
8
7
|
|
|
@@ -120,7 +119,10 @@ class ASTToQMODCode(ast.NodeVisitor):
|
|
|
120
119
|
return f"[{elements}]"
|
|
121
120
|
|
|
122
121
|
def visit_Subscript(self, node: ast.Subscript) -> str:
|
|
123
|
-
|
|
122
|
+
if not isinstance(node.value, ast.List):
|
|
123
|
+
return f"{self.visit(node.value)}[{_remove_redundant_parentheses(self.visit(node.slice))}]"
|
|
124
|
+
self.symbolic_imports["subscript"] = 1
|
|
125
|
+
return f"subscript({self.visit(node.value)}, {_remove_redundant_parentheses(self.visit(node.slice))})"
|
|
124
126
|
|
|
125
127
|
def visit_Slice(self, node: ast.Slice) -> str:
|
|
126
128
|
if node.lower is None or node.upper is None or node.step is not None:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections.abc import Mapping
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import cast
|
|
3
3
|
|
|
4
4
|
import black
|
|
5
5
|
|
|
@@ -108,7 +108,7 @@ class VariableDeclarationAssignment(Visitor):
|
|
|
108
108
|
|
|
109
109
|
def visit_QuantumBitvector(
|
|
110
110
|
self, qtype: QuantumBitvector
|
|
111
|
-
) -> tuple[str,
|
|
111
|
+
) -> tuple[str, list[str] | None]:
|
|
112
112
|
self.pretty_printer._imports["QArray"] = 1
|
|
113
113
|
|
|
114
114
|
element_type = self.pretty_printer.visit(qtype.element_type)
|
|
@@ -118,7 +118,7 @@ class VariableDeclarationAssignment(Visitor):
|
|
|
118
118
|
|
|
119
119
|
def visit_QuantumNumeric(
|
|
120
120
|
self, qtype: QuantumNumeric
|
|
121
|
-
) -> tuple[str,
|
|
121
|
+
) -> tuple[str, list[str] | None]:
|
|
122
122
|
self.pretty_printer._imports["QNum"] = 1
|
|
123
123
|
return "QNum", self.pretty_printer._get_qnum_properties(qtype)
|
|
124
124
|
|
|
@@ -130,12 +130,12 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
130
130
|
def __init__(self, decimal_precision: int = DEFAULT_DECIMAL_PRECISION) -> None:
|
|
131
131
|
self._level = 0
|
|
132
132
|
self._decimal_precision = decimal_precision
|
|
133
|
-
self._imports = {
|
|
133
|
+
self._imports: dict[str, int] = {}
|
|
134
134
|
self._import_enum = False
|
|
135
135
|
self._import_dataclass = False
|
|
136
136
|
self._import_annotated = False
|
|
137
137
|
self._symbolic_imports: dict[str, int] = dict()
|
|
138
|
-
self._functions:
|
|
138
|
+
self._functions: Mapping[str, QuantumFunctionDeclaration] | None = None
|
|
139
139
|
self._compilation_metadata: dict[str, CompilationMetadata] = dict()
|
|
140
140
|
|
|
141
141
|
def visit(self, node: NodeType) -> str:
|
|
@@ -204,16 +204,33 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
204
204
|
)
|
|
205
205
|
|
|
206
206
|
def _get_qfunc_decorator(self, func_decl: QuantumFunctionDeclaration) -> str:
|
|
207
|
-
|
|
207
|
+
if func_decl.permutation:
|
|
208
|
+
decorator = "@qperm"
|
|
209
|
+
self._imports["qperm"] = 1
|
|
210
|
+
else:
|
|
211
|
+
decorator = "@qfunc"
|
|
212
|
+
self._imports["qfunc"] = 1
|
|
213
|
+
|
|
208
214
|
if func_decl.name not in self._compilation_metadata:
|
|
209
|
-
return
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
215
|
+
return decorator
|
|
216
|
+
|
|
217
|
+
metadata = self._compilation_metadata[func_decl.name]
|
|
218
|
+
|
|
219
|
+
decorator_params: list[str] = []
|
|
220
|
+
if metadata.disable_perm_check:
|
|
221
|
+
decorator_params.append("disable_perm_check=True")
|
|
213
222
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
223
|
+
if metadata.disable_const_checks:
|
|
224
|
+
if metadata.disable_const_checks is True:
|
|
225
|
+
value = "True"
|
|
226
|
+
else:
|
|
227
|
+
value = f"[{', '.join(f'{param!r}' for param in metadata.disable_const_checks)}]"
|
|
228
|
+
decorator_params.append(f"disable_const_checks={value}")
|
|
229
|
+
|
|
230
|
+
if decorator_params:
|
|
231
|
+
return f"{decorator}({', '.join(decorator_params)})"
|
|
232
|
+
else:
|
|
233
|
+
return decorator
|
|
217
234
|
|
|
218
235
|
def visit_QuantumFunctionDeclaration(
|
|
219
236
|
self, func_decl: QuantumFunctionDeclaration
|
|
@@ -243,7 +260,7 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
243
260
|
return f"class {qstruct_decl.name}(QStruct):\n{self._visit_variables(qstruct_decl.fields)}\n"
|
|
244
261
|
|
|
245
262
|
def _visit_variables(
|
|
246
|
-
self, variables: Mapping[str,
|
|
263
|
+
self, variables: Mapping[str, ConcreteClassicalType | ConcreteQuantumType]
|
|
247
264
|
) -> str:
|
|
248
265
|
self._level += 1
|
|
249
266
|
variables_str = "".join(
|
|
@@ -262,7 +279,7 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
262
279
|
if port_decl.direction is not PortDeclarationDirection.Inout:
|
|
263
280
|
self._imports[port_decl.direction.name] = 1
|
|
264
281
|
var_type = f"{port_decl.direction.name}[{var_type}]"
|
|
265
|
-
if port_decl.type_modifier
|
|
282
|
+
if port_decl.type_modifier is TypeModifier.Const:
|
|
266
283
|
self._imports[port_decl.type_modifier.name] = 1
|
|
267
284
|
var_type = f"{port_decl.type_modifier.name}[{var_type}]"
|
|
268
285
|
return var_type
|
|
@@ -394,7 +411,12 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
394
411
|
def visit_AnonQuantumOperandDeclaration(
|
|
395
412
|
self, op_decl: AnonQuantumOperandDeclaration, no_param: bool = False
|
|
396
413
|
) -> str:
|
|
397
|
-
qcallable_identifier =
|
|
414
|
+
qcallable_identifier = {
|
|
415
|
+
(False, False): "QCallable",
|
|
416
|
+
(False, True): "QCallableList",
|
|
417
|
+
(True, False): "QPerm",
|
|
418
|
+
(True, True): "QPermList",
|
|
419
|
+
}[(op_decl.permutation, op_decl.is_list)]
|
|
398
420
|
self._imports[qcallable_identifier] = 1
|
|
399
421
|
args = ", ".join(
|
|
400
422
|
self._visit_operand_arg_decl(arg_decl)
|
|
@@ -494,7 +516,7 @@ class PythonPrettyPrinter(ModelVisitor):
|
|
|
494
516
|
return f"{self._indent}block({self._visit_body(block.statements)})\n"
|
|
495
517
|
|
|
496
518
|
def _visit_body(
|
|
497
|
-
self, body: StatementBlock, operand_arguments:
|
|
519
|
+
self, body: StatementBlock, operand_arguments: list[str] | None = None
|
|
498
520
|
) -> str:
|
|
499
521
|
if len(body) == 0:
|
|
500
522
|
return "lambda: []"
|
|
@@ -5,7 +5,6 @@ from typing import (
|
|
|
5
5
|
Any,
|
|
6
6
|
ForwardRef,
|
|
7
7
|
Literal,
|
|
8
|
-
Optional,
|
|
9
8
|
get_args,
|
|
10
9
|
get_origin,
|
|
11
10
|
)
|
|
@@ -15,6 +14,7 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
|
15
14
|
from classiq.interface.generator.functions.classical_type import (
|
|
16
15
|
Bool,
|
|
17
16
|
ClassicalArray,
|
|
17
|
+
ClassicalTuple,
|
|
18
18
|
Integer,
|
|
19
19
|
Real,
|
|
20
20
|
)
|
|
@@ -22,7 +22,7 @@ from classiq.interface.generator.functions.concrete_types import ConcreteClassic
|
|
|
22
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
|
-
from classiq.qmod.utilities import version_portable_get_args
|
|
25
|
+
from classiq.qmod.utilities import type_to_str, version_portable_get_args
|
|
26
26
|
|
|
27
27
|
CARRAY_ERROR_MESSAGE = (
|
|
28
28
|
"CArray accepts one or two generic parameters in the form "
|
|
@@ -30,10 +30,23 @@ CARRAY_ERROR_MESSAGE = (
|
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
def _has_struct_or_enum(classical_type: ConcreteClassicalType) -> bool:
|
|
34
|
+
if isinstance(classical_type, TypeName):
|
|
35
|
+
return True
|
|
36
|
+
if isinstance(classical_type, ClassicalArray):
|
|
37
|
+
return _has_struct_or_enum(classical_type.element_type)
|
|
38
|
+
if isinstance(classical_type, ClassicalTuple):
|
|
39
|
+
return any(
|
|
40
|
+
_has_struct_or_enum(element_type)
|
|
41
|
+
for element_type in classical_type.element_types
|
|
42
|
+
)
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
|
|
33
46
|
class PythonClassicalType:
|
|
34
47
|
def convert(
|
|
35
48
|
self, py_type: type, nested: bool = False
|
|
36
|
-
) ->
|
|
49
|
+
) -> ConcreteClassicalType | None:
|
|
37
50
|
if py_type is int:
|
|
38
51
|
return Integer().set_generative()
|
|
39
52
|
elif py_type is CInt:
|
|
@@ -47,21 +60,35 @@ class PythonClassicalType:
|
|
|
47
60
|
elif py_type is CBool:
|
|
48
61
|
return Bool()
|
|
49
62
|
elif get_origin(py_type) is list:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
element_py_type = get_args(py_type)[0]
|
|
64
|
+
element_type = self.convert(element_py_type, nested=True)
|
|
65
|
+
if element_type is None:
|
|
66
|
+
return None
|
|
67
|
+
if not element_type.is_generative and not _has_struct_or_enum(element_type):
|
|
68
|
+
raise ClassiqValueError(
|
|
69
|
+
f"Invalid type annotation: 'list' is generative but "
|
|
70
|
+
f"{type_to_str(element_py_type)!r} is declarative"
|
|
71
|
+
)
|
|
72
|
+
return ClassicalArray(element_type=element_type).set_generative()
|
|
53
73
|
elif get_origin(py_type) is CArray:
|
|
54
74
|
array_args = version_portable_get_args(py_type)
|
|
55
75
|
if len(array_args) == 1:
|
|
56
|
-
|
|
57
|
-
element_type=self.convert(array_args[0], nested=True)
|
|
58
|
-
)
|
|
76
|
+
length = None
|
|
59
77
|
elif len(array_args) == 2:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
78
|
+
length = Expression(expr=get_type_hint_expr(array_args[1]))
|
|
79
|
+
else:
|
|
80
|
+
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
|
81
|
+
element_type = self.convert(array_args[0], nested=True)
|
|
82
|
+
if element_type is None:
|
|
83
|
+
return None
|
|
84
|
+
if element_type.is_generative and not _has_struct_or_enum(element_type):
|
|
85
|
+
raise ClassiqValueError(
|
|
86
|
+
f"Invalid type annotation: 'CArray' is declarative but "
|
|
87
|
+
f"{type_to_str(array_args[0])!r} is generative"
|
|
63
88
|
)
|
|
64
|
-
|
|
89
|
+
return ClassicalArray(
|
|
90
|
+
element_type=self.convert(array_args[0], nested=True), length=length
|
|
91
|
+
)
|
|
65
92
|
elif inspect.isclass(py_type) and dataclasses.is_dataclass(py_type):
|
|
66
93
|
return self.register_struct(py_type)
|
|
67
94
|
elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
|