classiq 0.53.0__py3-none-any.whl → 0.55.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/__init__.py +1 -3
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
- classiq/_internals/__init__.py +0 -20
- classiq/_internals/api_wrapper.py +8 -8
- classiq/_internals/async_utils.py +1 -3
- classiq/_internals/authentication/auth0.py +5 -5
- classiq/_internals/authentication/device.py +5 -4
- classiq/_internals/authentication/password_manager.py +3 -3
- classiq/_internals/authentication/token_manager.py +3 -2
- classiq/_internals/client.py +10 -12
- classiq/_internals/config.py +2 -2
- classiq/_internals/jobs.py +7 -6
- classiq/_internals/type_validation.py +9 -9
- classiq/analyzer/__init__.py +1 -3
- classiq/analyzer/analyzer.py +8 -7
- classiq/analyzer/analyzer_utilities.py +8 -8
- classiq/analyzer/rb.py +11 -11
- classiq/applications/__init__.py +1 -3
- classiq/applications/chemistry/__init__.py +1 -3
- classiq/applications/chemistry/ansatz_parameters.py +4 -4
- classiq/applications/chemistry/chemistry_model_constructor.py +10 -9
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +26 -9
- classiq/applications/combinatorial_helpers/encoding_mapping.py +10 -10
- classiq/applications/combinatorial_helpers/encoding_utils.py +4 -4
- classiq/applications/combinatorial_helpers/memory.py +5 -7
- classiq/applications/combinatorial_helpers/optimization_model.py +43 -24
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +4 -6
- classiq/applications/combinatorial_helpers/pyomo_utils.py +95 -24
- classiq/applications/combinatorial_helpers/sympy_utils.py +2 -2
- classiq/applications/combinatorial_helpers/transformations/encoding.py +8 -8
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +5 -5
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +7 -9
- classiq/applications/combinatorial_helpers/transformations/penalty.py +1 -2
- classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +1 -2
- classiq/applications/combinatorial_helpers/transformations/slack_variables.py +1 -2
- classiq/applications/combinatorial_optimization/__init__.py +1 -3
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
- classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
- classiq/applications/finance/__init__.py +1 -3
- classiq/applications/grover/__init__.py +1 -3
- classiq/applications/grover/grover_model_constructor.py +7 -9
- classiq/applications/hamiltonian/pauli_decomposition.py +6 -6
- classiq/applications/qnn/__init__.py +1 -3
- classiq/applications/qnn/circuit_utils.py +5 -5
- classiq/applications/qnn/datasets/__init__.py +1 -3
- classiq/applications/qnn/datasets/dataset_base_classes.py +5 -4
- classiq/applications/qnn/datasets/dataset_parity.py +2 -2
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
- classiq/applications/qnn/qlayer.py +3 -3
- classiq/applications/qnn/torch_utils.py +2 -2
- classiq/applications/qnn/types.py +5 -5
- classiq/applications/qsvm/qsvm.py +1 -3
- classiq/applications/qsvm/qsvm_data_generation.py +3 -3
- classiq/applications/qsvm/qsvm_model_constructor.py +5 -5
- classiq/execution/__init__.py +1 -3
- classiq/execution/all_hardware_devices.py +1 -3
- classiq/execution/execution_session.py +16 -16
- classiq/execution/jobs.py +4 -4
- classiq/execution/qaoa.py +3 -3
- classiq/execution/qnn.py +3 -3
- classiq/executor.py +3 -3
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +9 -10
- classiq/interface/analyzer/cytoscape_graph.py +5 -5
- classiq/interface/analyzer/result.py +17 -17
- classiq/interface/applications/qsvm.py +6 -10
- classiq/interface/backend/backend_preferences.py +4 -3
- classiq/interface/backend/ionq/ionq_quantum_program.py +4 -5
- classiq/interface/backend/pydantic_backend.py +1 -2
- classiq/interface/chemistry/fermionic_operator.py +5 -5
- classiq/interface/chemistry/ground_state_problem.py +7 -8
- classiq/interface/chemistry/molecule.py +4 -4
- classiq/interface/chemistry/operator.py +11 -13
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
- classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
- classiq/interface/combinatorial_optimization/examples/mht.py +2 -3
- classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
- classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +5 -7
- classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
- classiq/interface/combinatorial_optimization/result.py +1 -3
- classiq/interface/debug_info/debug_info.py +8 -7
- classiq/interface/exceptions.py +8 -6
- classiq/interface/execution/jobs.py +2 -2
- classiq/interface/execution/primitives.py +3 -3
- classiq/interface/executor/aws_execution_cost.py +4 -4
- classiq/interface/executor/execution_request.py +2 -3
- classiq/interface/executor/execution_result.py +3 -3
- classiq/interface/executor/iqae_result.py +3 -5
- classiq/interface/executor/optimizer_preferences.py +2 -2
- classiq/interface/executor/quantum_code.py +6 -6
- classiq/interface/executor/register_initialization.py +2 -4
- classiq/interface/executor/result.py +23 -27
- classiq/interface/executor/vqe_result.py +8 -8
- classiq/interface/finance/function_input.py +2 -2
- classiq/interface/finance/gaussian_model_input.py +5 -5
- classiq/interface/finance/log_normal_model_input.py +2 -2
- classiq/interface/finance/model_input.py +1 -2
- classiq/interface/generator/adjacency.py +1 -3
- classiq/interface/generator/ansatz_library.py +4 -4
- classiq/interface/generator/application_apis/finance_declarations.py +1 -1
- classiq/interface/generator/arith/argument_utils.py +3 -3
- classiq/interface/generator/arith/arithmetic.py +7 -7
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +5 -5
- classiq/interface/generator/arith/arithmetic_expression_abc.py +11 -11
- classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -7
- classiq/interface/generator/arith/arithmetic_expression_validator.py +8 -8
- classiq/interface/generator/arith/arithmetic_operations.py +4 -3
- classiq/interface/generator/arith/arithmetic_param_getters.py +6 -6
- classiq/interface/generator/arith/arithmetic_result_builder.py +9 -9
- classiq/interface/generator/arith/ast_node_rewrite.py +2 -1
- classiq/interface/generator/arith/binary_ops.py +10 -13
- classiq/interface/generator/arith/extremum_operations.py +3 -2
- classiq/interface/generator/arith/logical_ops.py +7 -6
- classiq/interface/generator/arith/number_utils.py +4 -4
- classiq/interface/generator/arith/register_user_input.py +4 -4
- classiq/interface/generator/arith/unary_ops.py +2 -1
- classiq/interface/generator/builtin_api_builder.py +2 -1
- classiq/interface/generator/circuit_code/circuit_code.py +4 -4
- classiq/interface/generator/circuit_code/types_and_constants.py +3 -5
- classiq/interface/generator/complex_type.py +1 -2
- classiq/interface/generator/control_state.py +2 -2
- classiq/interface/generator/custom_ansatz.py +1 -3
- classiq/interface/generator/distance.py +3 -5
- classiq/interface/generator/excitations.py +3 -2
- classiq/interface/generator/expressions/enums/finance_functions.py +1 -3
- classiq/interface/generator/expressions/evaluated_expression.py +4 -3
- classiq/interface/generator/expressions/expression.py +4 -5
- classiq/interface/generator/expressions/expression_constants.py +4 -4
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +2 -1
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +2 -1
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +2 -1
- classiq/interface/generator/expressions/qmod_sized_proxy.py +2 -1
- classiq/interface/generator/expressions/qmod_struct_instance.py +2 -1
- classiq/interface/generator/expressions/sympy_supported_expressions.py +11 -13
- classiq/interface/generator/finance.py +2 -2
- classiq/interface/generator/function_param_library.py +6 -6
- classiq/interface/generator/function_params.py +13 -19
- classiq/interface/generator/functions/builtins/internal_operators.py +9 -1
- classiq/interface/generator/functions/classical_function_declaration.py +4 -3
- classiq/interface/generator/functions/classical_type.py +13 -13
- classiq/interface/generator/functions/concrete_types.py +1 -2
- classiq/interface/generator/functions/function_declaration.py +1 -1
- classiq/interface/generator/functions/qmod_python_interface.py +2 -1
- classiq/interface/generator/functions/type_name.py +3 -2
- classiq/interface/generator/generated_circuit_data.py +33 -22
- classiq/interface/generator/grover_diffuser.py +7 -7
- classiq/interface/generator/grover_operator.py +2 -2
- classiq/interface/generator/hardware/hardware_data.py +7 -6
- classiq/interface/generator/hardware_efficient_ansatz.py +8 -8
- classiq/interface/generator/identity.py +5 -6
- classiq/interface/generator/linear_pauli_rotations.py +6 -6
- classiq/interface/generator/mcu.py +2 -2
- classiq/interface/generator/mcx.py +6 -6
- classiq/interface/generator/model/__init__.py +1 -3
- classiq/interface/generator/model/constraints.py +2 -2
- classiq/interface/generator/model/model.py +5 -6
- classiq/interface/generator/model/preferences/preferences.py +11 -6
- classiq/interface/generator/model/quantum_register.py +6 -11
- classiq/interface/generator/oracles/arithmetic_oracle.py +1 -2
- classiq/interface/generator/oracles/custom_oracle.py +2 -2
- classiq/interface/generator/oracles/oracle_abc.py +6 -5
- classiq/interface/generator/partitioned_register.py +6 -5
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +8 -7
- classiq/interface/generator/qpe.py +4 -4
- classiq/interface/generator/qsvm.py +3 -3
- classiq/interface/generator/quantum_function_call.py +24 -29
- classiq/interface/generator/quantum_program.py +9 -9
- classiq/interface/generator/register_role.py +2 -4
- classiq/interface/generator/slice_parsing_utils.py +4 -3
- classiq/interface/generator/standard_gates/standard_gates.py +3 -3
- classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
- classiq/interface/generator/state_preparation/distributions.py +6 -5
- classiq/interface/generator/state_preparation/metrics.py +2 -4
- classiq/interface/generator/state_preparation/state_preparation.py +4 -4
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +3 -3
- classiq/interface/generator/transpiler_basis_gates.py +2 -2
- classiq/interface/generator/types/compilation_metadata.py +5 -0
- classiq/interface/generator/types/enum_declaration.py +2 -3
- classiq/interface/generator/types/qstruct_declaration.py +2 -1
- classiq/interface/generator/types/struct_declaration.py +3 -2
- classiq/interface/generator/ucc.py +2 -1
- classiq/interface/generator/unitary_gate.py +2 -2
- classiq/interface/generator/user_defined_function_params.py +1 -1
- classiq/interface/generator/validations/flow_graph.py +6 -5
- classiq/interface/generator/validations/validator_functions.py +3 -2
- classiq/interface/generator/visitor.py +9 -14
- classiq/interface/hardware.py +5 -6
- classiq/interface/helpers/custom_encoders.py +2 -2
- classiq/interface/helpers/custom_pydantic_types.py +8 -9
- classiq/interface/helpers/hashable_mixin.py +3 -2
- classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
- classiq/interface/helpers/pydantic_model_helpers.py +4 -3
- classiq/interface/helpers/validation_helpers.py +2 -2
- classiq/interface/ide/ide_data.py +11 -15
- classiq/interface/ide/visual_model.py +22 -22
- classiq/interface/jobs.py +2 -2
- classiq/interface/model/bind_operation.py +5 -4
- classiq/interface/model/classical_parameter_declaration.py +2 -2
- classiq/interface/model/control.py +22 -1
- classiq/interface/model/handle_binding.py +3 -2
- classiq/interface/model/inplace_binary_operation.py +2 -1
- classiq/interface/model/model.py +16 -11
- classiq/interface/model/native_function_definition.py +1 -1
- classiq/interface/model/port_declaration.py +2 -2
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +3 -2
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +4 -27
- classiq/interface/model/quantum_expressions/quantum_expression.py +8 -7
- classiq/interface/model/quantum_function_call.py +9 -14
- classiq/interface/model/quantum_function_declaration.py +10 -12
- classiq/interface/model/quantum_lambda_function.py +3 -16
- classiq/interface/model/quantum_statement.py +7 -3
- classiq/interface/model/quantum_type.py +5 -5
- classiq/interface/model/statement_block.py +2 -3
- classiq/interface/model/validation_handle.py +5 -4
- classiq/interface/server/global_versions.py +3 -3
- classiq/model_expansions/atomic_expression_functions_defs.py +3 -2
- classiq/model_expansions/capturing/captured_var_manager.py +4 -6
- classiq/model_expansions/capturing/propagated_var_stack.py +7 -7
- classiq/model_expansions/closure.py +83 -12
- classiq/model_expansions/evaluators/arg_type_match.py +3 -2
- classiq/model_expansions/evaluators/argument_types.py +3 -3
- classiq/model_expansions/evaluators/control.py +3 -3
- classiq/model_expansions/evaluators/parameter_types.py +7 -7
- classiq/model_expansions/evaluators/quantum_type_utils.py +2 -1
- classiq/model_expansions/evaluators/type_type_match.py +1 -1
- classiq/model_expansions/expression_evaluator.py +10 -9
- classiq/model_expansions/expression_renamer.py +6 -6
- classiq/model_expansions/function_builder.py +13 -12
- classiq/model_expansions/generative_functions.py +5 -4
- classiq/model_expansions/interpreter.py +20 -11
- classiq/model_expansions/model_tables.py +14 -14
- classiq/model_expansions/quantum_operations/bind.py +2 -4
- classiq/model_expansions/quantum_operations/classicalif.py +1 -1
- classiq/model_expansions/quantum_operations/control.py +81 -24
- classiq/model_expansions/quantum_operations/emitter.py +33 -20
- classiq/model_expansions/quantum_operations/expression_operation.py +47 -16
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +160 -35
- classiq/model_expansions/quantum_operations/phase.py +6 -6
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +28 -31
- classiq/model_expansions/quantum_operations/quantum_function_call.py +9 -0
- classiq/model_expansions/quantum_operations/repeat.py +1 -3
- classiq/model_expansions/quantum_operations/within_apply.py +0 -16
- classiq/model_expansions/scope.py +11 -10
- classiq/model_expansions/scope_initialization.py +5 -5
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +6 -6
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +2 -2
- classiq/model_expansions/visitors/variable_references.py +5 -4
- classiq/qmod/builtins/classical_execution_primitives.py +9 -9
- classiq/qmod/builtins/functions/__init__.py +72 -55
- classiq/qmod/builtins/functions/amplitude_estimation.py +4 -1
- classiq/qmod/builtins/functions/arithmetic.py +14 -1
- classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +86 -6
- classiq/qmod/builtins/functions/grover.py +41 -45
- classiq/qmod/builtins/functions/hea.py +60 -4
- classiq/qmod/builtins/functions/linear_pauli_rotation.py +26 -4
- classiq/qmod/builtins/functions/modular_exponentiation.py +90 -29
- classiq/qmod/builtins/functions/operators.py +1 -1
- classiq/qmod/builtins/functions/qaoa_penalty.py +14 -5
- classiq/qmod/builtins/functions/qft_functions.py +57 -0
- classiq/qmod/builtins/functions/qpe.py +20 -4
- classiq/qmod/builtins/functions/qsvt.py +49 -4
- classiq/qmod/builtins/functions/standard_gates.py +4 -4
- classiq/qmod/builtins/functions/state_preparation.py +92 -10
- classiq/qmod/builtins/functions/swap_test.py +7 -1
- classiq/qmod/builtins/functions/utility_functions.py +43 -0
- classiq/qmod/builtins/functions/variational.py +18 -2
- classiq/qmod/builtins/operations.py +117 -22
- classiq/qmod/cfunc.py +2 -2
- classiq/qmod/classical_function.py +3 -7
- classiq/qmod/create_model_function.py +16 -17
- classiq/qmod/declaration_inferrer.py +7 -10
- classiq/qmod/expression_query.py +3 -3
- classiq/qmod/generative.py +2 -1
- classiq/qmod/model_state_container.py +10 -8
- classiq/qmod/native/__init__.py +1 -3
- classiq/qmod/native/expression_to_qmod.py +9 -8
- classiq/qmod/native/pretty_printer.py +12 -6
- classiq/qmod/pretty_print/__init__.py +1 -3
- classiq/qmod/pretty_print/expression_to_python.py +13 -12
- classiq/qmod/pretty_print/pretty_printer.py +38 -23
- classiq/qmod/python_classical_type.py +8 -4
- classiq/qmod/qfunc.py +4 -4
- classiq/qmod/qmod_variable.py +11 -10
- classiq/qmod/quantum_expandable.py +12 -15
- classiq/qmod/quantum_function.py +35 -22
- classiq/qmod/semantics/annotation.py +1 -1
- classiq/qmod/semantics/error_manager.py +8 -7
- classiq/qmod/semantics/static_semantics_visitor.py +19 -24
- classiq/qmod/semantics/validation/constants_validation.py +1 -1
- classiq/qmod/semantics/validation/func_call_validation.py +2 -2
- classiq/qmod/semantics/validation/main_validation.py +33 -0
- classiq/qmod/semantics/validation/types_validation.py +2 -1
- classiq/qmod/symbolic.py +5 -8
- classiq/qmod/symbolic_type.py +2 -2
- classiq/qmod/synthesize_separately.py +1 -2
- {classiq-0.53.0.dist-info → classiq-0.55.0.dist-info}/METADATA +1 -1
- {classiq-0.53.0.dist-info → classiq-0.55.0.dist-info}/RECORD +300 -297
- classiq/qmod/builtins/functions/qft.py +0 -23
- {classiq-0.53.0.dist-info → classiq-0.55.0.dist-info}/WHEEL +0 -0
@@ -1,8 +1,7 @@
|
|
1
1
|
import ast
|
2
2
|
import inspect
|
3
|
-
import sys
|
4
3
|
from textwrap import dedent
|
5
|
-
from typing import Any, Callable
|
4
|
+
from typing import Any, Callable
|
6
5
|
|
7
6
|
from classiq.interface.exceptions import ClassiqValueError
|
8
7
|
|
@@ -17,16 +16,13 @@ def _unparse_function_body(code: str, func: ast.FunctionDef) -> str:
|
|
17
16
|
|
18
17
|
|
19
18
|
class CFunc:
|
20
|
-
def __init__(self, py_callable: Callable[[], None], caller_locals:
|
19
|
+
def __init__(self, py_callable: Callable[[], None], caller_locals: dict[str, Any]):
|
21
20
|
code = dedent(inspect.getsource(py_callable))
|
22
21
|
func = ast.parse(code).body[0]
|
23
22
|
if not isinstance(func, ast.FunctionDef):
|
24
23
|
raise ClassiqValueError("Use @cfunc to decorate a function")
|
25
24
|
if len(func.args.args) > 0:
|
26
25
|
raise ClassiqValueError("A @cfunc must receive no arguments")
|
27
|
-
|
28
|
-
self.code = "\n".join([ast.unparse(statement) for statement in func.body])
|
29
|
-
else:
|
30
|
-
self.code = _unparse_function_body(code, func)
|
26
|
+
self.code = "\n".join([ast.unparse(statement) for statement in func.body])
|
31
27
|
|
32
28
|
self._caller_constants = caller_locals
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import TYPE_CHECKING,
|
1
|
+
from typing import TYPE_CHECKING, Optional, Union, cast
|
2
2
|
|
3
3
|
from classiq.interface.exceptions import ClassiqError
|
4
4
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
@@ -60,6 +60,7 @@ def create_model(
|
|
60
60
|
user_gen_functions = {
|
61
61
|
gen_func._py_callable.__name__ for gen_func in GEN_QFUNCS
|
62
62
|
} - set(BUILTIN_FUNCTION_DECLARATIONS.keys())
|
63
|
+
|
63
64
|
if len(user_gen_functions) > 0 and is_generative_expansion_enabled():
|
64
65
|
model = _expand_generative_model(
|
65
66
|
(
|
@@ -100,11 +101,17 @@ def _expand_generative_model(
|
|
100
101
|
def _dummy() -> None:
|
101
102
|
pass
|
102
103
|
|
104
|
+
functions_compilation_metadata = {
|
105
|
+
dec_func._py_callable.__name__: dec_func.compilation_metadata
|
106
|
+
for dec_func in DEC_QFUNCS
|
107
|
+
if dec_func.compilation_metadata is not None
|
108
|
+
}
|
103
109
|
model = _dummy.create_model(
|
104
110
|
constraints,
|
105
111
|
execution_preferences,
|
106
112
|
preferences,
|
107
113
|
classical_execution_function,
|
114
|
+
functions_compilation_metadata,
|
108
115
|
)
|
109
116
|
generative_functions = _get_generative_functions(gen_main, preferences)
|
110
117
|
model.functions = generative_functions
|
@@ -116,7 +123,7 @@ def _expand_generative_model(
|
|
116
123
|
|
117
124
|
def _get_generative_functions(
|
118
125
|
gen_main: QFunc, preferences: Optional[Preferences]
|
119
|
-
) ->
|
126
|
+
) -> list[NativeFunctionDefinition]:
|
120
127
|
# The Interpreter accepts a model and a list of generative functions.
|
121
128
|
# Since the main function is generative, it can only be expanded using the
|
122
129
|
# Interpreter.
|
@@ -154,10 +161,11 @@ def _get_wrapper_main(gen_main: QFunc, preferences: Optional[Preferences]) -> Mo
|
|
154
161
|
)
|
155
162
|
|
156
163
|
|
157
|
-
def _get_all_model_functions_as_generative_functions() ->
|
164
|
+
def _get_all_model_functions_as_generative_functions() -> list[GenerativeQFunc]:
|
158
165
|
|
159
166
|
gen_functions = list(GEN_QFUNCS) + [
|
160
|
-
|
167
|
+
GenerativeQFunc(dec_func._py_callable, dec_func.func_decl)
|
168
|
+
for dec_func in DEC_QFUNCS
|
161
169
|
]
|
162
170
|
return [
|
163
171
|
(
|
@@ -173,26 +181,17 @@ def _get_all_model_functions_as_generative_functions() -> List[GenerativeQFunc]:
|
|
173
181
|
]
|
174
182
|
|
175
183
|
|
176
|
-
def _get_gen_from_dec(dec_func: QFunc) -> GenerativeQFunc:
|
177
|
-
synthesis_data = dec_func.synthesis_data
|
178
|
-
if synthesis_data is not None and synthesis_data.should_synthesize_separately:
|
179
|
-
raise ClassiqError(
|
180
|
-
"""The model contains generative functions,
|
181
|
-
which cannot coexist with functions marked for separate synthesis"""
|
182
|
-
)
|
183
|
-
return GenerativeQFunc(dec_func._py_callable, dec_func.func_decl)
|
184
|
-
|
185
|
-
|
186
184
|
def _interpret_generative_model(
|
187
|
-
gen_model: Model, gen_functions:
|
188
|
-
) ->
|
185
|
+
gen_model: Model, gen_functions: list[GenerativeQFunc]
|
186
|
+
) -> dict[str, NativeFunctionDefinition]:
|
189
187
|
resolve_function_calls(
|
190
188
|
gen_model,
|
191
189
|
{gen_func.func_decl.name: gen_func.func_decl for gen_func in gen_functions},
|
192
190
|
)
|
193
191
|
interpreter = Interpreter(gen_model, gen_functions, is_frontend=True)
|
194
192
|
set_frontend_interpreter(interpreter)
|
195
|
-
|
193
|
+
expand_model = interpreter.expand()
|
194
|
+
functions_dict = nameables_to_dict(expand_model.functions)
|
196
195
|
|
197
196
|
# Inline _gen_main call in main
|
198
197
|
expanded_gen_main_name = cast(
|
@@ -1,15 +1,12 @@
|
|
1
1
|
import dataclasses
|
2
2
|
import sys
|
3
|
+
from collections.abc import Sequence
|
3
4
|
from enum import EnumMeta
|
4
5
|
from typing import (
|
5
6
|
Any,
|
6
7
|
Callable,
|
7
|
-
List,
|
8
8
|
Literal,
|
9
9
|
Optional,
|
10
|
-
Sequence,
|
11
|
-
Tuple,
|
12
|
-
Type,
|
13
10
|
get_args,
|
14
11
|
get_origin,
|
15
12
|
overload,
|
@@ -91,7 +88,7 @@ def python_type_to_qmod(
|
|
91
88
|
|
92
89
|
def _extract_port_decl(name: Optional[str], py_type: Any) -> AnonPortDeclaration:
|
93
90
|
# FIXME: CAD-13409
|
94
|
-
qtype:
|
91
|
+
qtype: type[QVar] = QVar.from_type_hint(py_type) # type:ignore[assignment]
|
95
92
|
direction = qtype.port_direction(py_type)
|
96
93
|
if isinstance(py_type, _AnnotatedAlias):
|
97
94
|
py_type = py_type.__args__[0]
|
@@ -128,7 +125,7 @@ def _extract_operand_decl(
|
|
128
125
|
return param
|
129
126
|
|
130
127
|
|
131
|
-
def _extract_operand_param(py_type: Any) ->
|
128
|
+
def _extract_operand_param(py_type: Any) -> tuple[Optional[str], Any]:
|
132
129
|
if sys.version_info[0:2] < (3, 9) or get_origin(py_type) is not Annotated:
|
133
130
|
return None, py_type
|
134
131
|
args = get_args(py_type)
|
@@ -152,22 +149,22 @@ def _extract_operand_param(py_type: Any) -> Tuple[Optional[str], Any]:
|
|
152
149
|
|
153
150
|
@overload
|
154
151
|
def _extract_positional_args(
|
155
|
-
args: Sequence[
|
152
|
+
args: Sequence[tuple[str, Any]], qmodule: Optional[ModelStateContainer]
|
156
153
|
) -> Sequence[PositionalArg]:
|
157
154
|
pass
|
158
155
|
|
159
156
|
|
160
157
|
@overload
|
161
158
|
def _extract_positional_args(
|
162
|
-
args: Sequence[
|
159
|
+
args: Sequence[tuple[Optional[str], Any]], qmodule: Optional[ModelStateContainer]
|
163
160
|
) -> Sequence[AnonPositionalArg]:
|
164
161
|
pass
|
165
162
|
|
166
163
|
|
167
164
|
def _extract_positional_args(
|
168
|
-
args: Sequence[
|
165
|
+
args: Sequence[tuple[Optional[str], Any]], qmodule: Optional[ModelStateContainer]
|
169
166
|
) -> Sequence[AnonPositionalArg]:
|
170
|
-
result:
|
167
|
+
result: list[AnonPositionalArg] = []
|
171
168
|
for name, py_type in args:
|
172
169
|
if name == "return":
|
173
170
|
continue
|
classiq/qmod/expression_query.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import TYPE_CHECKING
|
1
|
+
from typing import TYPE_CHECKING
|
2
2
|
|
3
3
|
from classiq.interface.generator.arith.arithmetic import compute_arithmetic_result_type
|
4
4
|
from classiq.interface.generator.arith.number_utils import MAXIMAL_MACHINE_PRECISION
|
@@ -9,10 +9,10 @@ from classiq.qmod.symbolic_type import SymbolicTypes
|
|
9
9
|
|
10
10
|
|
11
11
|
def get_expression_numeric_attributes(
|
12
|
-
vars:
|
12
|
+
vars: list[QNum],
|
13
13
|
expr: SymbolicTypes,
|
14
14
|
machine_precision: int = MAXIMAL_MACHINE_PRECISION,
|
15
|
-
) ->
|
15
|
+
) -> tuple[int, bool, int]:
|
16
16
|
"""
|
17
17
|
Computes and returns the numeric attributes of a given symbolic expression.
|
18
18
|
|
classiq/qmod/generative.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
from collections.abc import Iterator
|
1
2
|
from contextlib import contextmanager
|
2
|
-
from typing import TYPE_CHECKING, Any,
|
3
|
+
from typing import TYPE_CHECKING, Any, Optional
|
3
4
|
|
4
5
|
from classiq.interface.exceptions import ClassiqError
|
5
6
|
from classiq.interface.generator.expressions.expression import Expression
|
@@ -1,18 +1,20 @@
|
|
1
|
-
from typing import Dict
|
2
|
-
|
3
1
|
from classiq.interface.generator.constant import Constant
|
2
|
+
from classiq.interface.generator.types.compilation_metadata import CompilationMetadata
|
4
3
|
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
5
4
|
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
6
5
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
7
|
-
from classiq.interface.model.native_function_definition import
|
6
|
+
from classiq.interface.model.native_function_definition import (
|
7
|
+
NativeFunctionDefinition,
|
8
|
+
)
|
8
9
|
|
9
10
|
|
10
11
|
class ModelStateContainer:
|
11
|
-
enum_decls:
|
12
|
-
type_decls:
|
13
|
-
qstruct_decls:
|
14
|
-
native_defs:
|
15
|
-
constants:
|
12
|
+
enum_decls: dict[str, EnumDeclaration]
|
13
|
+
type_decls: dict[str, StructDeclaration]
|
14
|
+
qstruct_decls: dict[str, QStructDeclaration]
|
15
|
+
native_defs: dict[str, NativeFunctionDefinition]
|
16
|
+
constants: dict[str, Constant]
|
17
|
+
functions_compilation_metadata: dict[str, CompilationMetadata]
|
16
18
|
|
17
19
|
|
18
20
|
QMODULE = ModelStateContainer()
|
classiq/qmod/native/__init__.py
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
import ast
|
2
2
|
import re
|
3
|
+
from collections.abc import Mapping
|
3
4
|
from dataclasses import dataclass
|
4
|
-
from typing import Callable,
|
5
|
+
from typing import Callable, Optional
|
5
6
|
|
6
7
|
import numpy as np
|
7
8
|
|
8
9
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
9
10
|
|
10
11
|
IDENTIFIER = re.compile(r"[a-zA-Z_]\w*")
|
11
|
-
BINARY_OPS: Mapping[
|
12
|
+
BINARY_OPS: Mapping[type[ast.operator], str] = {
|
12
13
|
ast.Add: "+",
|
13
14
|
ast.Sub: "-",
|
14
15
|
ast.Mult: "*",
|
@@ -21,14 +22,14 @@ BINARY_OPS: Mapping[Type[ast.operator], str] = {
|
|
21
22
|
ast.LShift: "<<",
|
22
23
|
ast.RShift: ">>",
|
23
24
|
}
|
24
|
-
BOOL_OPS: Mapping[
|
25
|
-
UNARY_OPS: Mapping[
|
25
|
+
BOOL_OPS: Mapping[type[ast.boolop], str] = {ast.And: "and", ast.Or: "or"}
|
26
|
+
UNARY_OPS: Mapping[type[ast.unaryop], str] = {
|
26
27
|
ast.UAdd: "+",
|
27
28
|
ast.USub: "-",
|
28
29
|
ast.Invert: "~",
|
29
30
|
ast.Not: "not",
|
30
31
|
}
|
31
|
-
COMPARE_OPS: Mapping[
|
32
|
+
COMPARE_OPS: Mapping[type[ast.cmpop], str] = {
|
32
33
|
ast.Eq: "==",
|
33
34
|
ast.NotEq: "!=",
|
34
35
|
ast.Lt: "<",
|
@@ -139,7 +140,7 @@ class ASTToQMODCode:
|
|
139
140
|
else:
|
140
141
|
raise AssertionError("Error parsing expression: unsupported AST node.")
|
141
142
|
|
142
|
-
def indent_items(self, items: Callable[[],
|
143
|
+
def indent_items(self, items: Callable[[], list[str]]) -> str:
|
143
144
|
should_indent = (
|
144
145
|
len("".join([i.strip() for i in items()])) >= LIST_FORMAT_CHAR_LIMIT
|
145
146
|
)
|
@@ -165,8 +166,8 @@ class ASTToQMODCode:
|
|
165
166
|
def _remove_redundant_parentheses(expr: str) -> str:
|
166
167
|
if not (expr.startswith("(") and expr.endswith(")")):
|
167
168
|
return expr
|
168
|
-
parentheses_map:
|
169
|
-
stack:
|
169
|
+
parentheses_map: dict[int, int] = dict()
|
170
|
+
stack: list[int] = []
|
170
171
|
for index, char in enumerate(expr):
|
171
172
|
if char == "(":
|
172
173
|
stack.append(index)
|
@@ -1,4 +1,5 @@
|
|
1
|
-
from
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import Optional, Union
|
2
3
|
|
3
4
|
from classiq.interface.generator.constant import Constant
|
4
5
|
from classiq.interface.generator.expressions.expression import Expression
|
@@ -135,7 +136,7 @@ class DSLPrettyPrinter(Visitor):
|
|
135
136
|
def visit_EnumDeclaration(self, enum_decl: EnumDeclaration) -> str:
|
136
137
|
return f"enum {enum_decl.name} {{\n{self._visit_members(enum_decl.members)}}}\n"
|
137
138
|
|
138
|
-
def _visit_members(self, members:
|
139
|
+
def _visit_members(self, members: dict[str, int]) -> str:
|
139
140
|
self._level += 1
|
140
141
|
members_str = "".join(
|
141
142
|
f"{self._indent}{self.visit(member_name)} = {member_value};\n"
|
@@ -252,7 +253,12 @@ class DSLPrettyPrinter(Visitor):
|
|
252
253
|
def visit_Control(self, op: Control) -> str:
|
253
254
|
control = f"{self._indent}control ({self.visit(op.expression)}) {{\n"
|
254
255
|
control += self._visit_body(op.body)
|
255
|
-
control += f"{self._indent}}}
|
256
|
+
control += f"{self._indent}}}"
|
257
|
+
if op.else_block is not None:
|
258
|
+
control += " else {\n"
|
259
|
+
control += self._visit_body(op.else_block)
|
260
|
+
control += f"{self._indent}}}"
|
261
|
+
control += "\n"
|
256
262
|
return control
|
257
263
|
|
258
264
|
def visit_PhaseOperation(self, op: PhaseOperation) -> str:
|
@@ -310,7 +316,7 @@ class DSLPrettyPrinter(Visitor):
|
|
310
316
|
def visit_InplaceBinaryOperation(self, op: InplaceBinaryOperation) -> str:
|
311
317
|
return f"{self._indent}{op.operation.value}({self.visit(op.value)}, {self.visit(op.target)});\n"
|
312
318
|
|
313
|
-
def _visit_pack_expr(self, vars:
|
319
|
+
def _visit_pack_expr(self, vars: list[HandleBinding]) -> str:
|
314
320
|
if len(vars) == 1:
|
315
321
|
return self.visit(vars[0])
|
316
322
|
|
@@ -324,7 +330,7 @@ class DSLPrettyPrinter(Visitor):
|
|
324
330
|
|
325
331
|
def visit_QuantumLambdaFunction(self, qlambda: QuantumLambdaFunction) -> str:
|
326
332
|
positional_args = ", ".join(
|
327
|
-
qlambda.
|
333
|
+
qlambda.pos_rename_params[idx]
|
328
334
|
for idx, arg_decl in enumerate(
|
329
335
|
qlambda.func_decl.positional_arg_declarations
|
330
336
|
)
|
@@ -358,7 +364,7 @@ class DSLPrettyPrinter(Visitor):
|
|
358
364
|
) -> str:
|
359
365
|
return f"{self._indent}{self.visit(amplitude_loading_op.result_var)} *= {self.visit(amplitude_loading_op.expression)};\n"
|
360
366
|
|
361
|
-
def _print_bind_handles(self, handles:
|
367
|
+
def _print_bind_handles(self, handles: list[HandleBinding]) -> str:
|
362
368
|
if len(handles) == 1:
|
363
369
|
return self.visit(handles[0])
|
364
370
|
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import ast
|
2
2
|
import re
|
3
|
+
from collections.abc import Mapping
|
3
4
|
from dataclasses import dataclass
|
4
|
-
from typing import Callable
|
5
|
+
from typing import Callable
|
5
6
|
|
6
7
|
import numpy as np
|
7
8
|
|
@@ -9,7 +10,7 @@ import classiq
|
|
9
10
|
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
10
11
|
|
11
12
|
IDENTIFIER = re.compile(r"[a-zA-Z_]\w*")
|
12
|
-
BINARY_OPS: Mapping[
|
13
|
+
BINARY_OPS: Mapping[type[ast.operator], str] = {
|
13
14
|
ast.Add: "+",
|
14
15
|
ast.Sub: "-",
|
15
16
|
ast.Mult: "*",
|
@@ -22,14 +23,14 @@ BINARY_OPS: Mapping[Type[ast.operator], str] = {
|
|
22
23
|
ast.LShift: "<<",
|
23
24
|
ast.RShift: ">>",
|
24
25
|
}
|
25
|
-
BOOL_OPS: Mapping[
|
26
|
-
UNARY_OPS: Mapping[
|
26
|
+
BOOL_OPS: Mapping[type[ast.boolop], str] = {ast.And: "and", ast.Or: "or"}
|
27
|
+
UNARY_OPS: Mapping[type[ast.unaryop], str] = {
|
27
28
|
ast.UAdd: "+",
|
28
29
|
ast.USub: "-",
|
29
30
|
ast.Invert: "~",
|
30
31
|
ast.Not: "not",
|
31
32
|
}
|
32
|
-
COMPARE_OPS: Mapping[
|
33
|
+
COMPARE_OPS: Mapping[type[ast.cmpop], str] = {
|
33
34
|
ast.Eq: "==",
|
34
35
|
ast.NotEq: "!=",
|
35
36
|
ast.Lt: "<",
|
@@ -43,8 +44,8 @@ LIST_FORMAT_CHAR_LIMIT = 20
|
|
43
44
|
@dataclass
|
44
45
|
class ASTToQMODCode(ast.NodeVisitor):
|
45
46
|
level: int
|
46
|
-
imports:
|
47
|
-
symbolic_imports:
|
47
|
+
imports: dict[str, int]
|
48
|
+
symbolic_imports: dict[str, int]
|
48
49
|
decimal_precision: int
|
49
50
|
indent_seq: str = " "
|
50
51
|
|
@@ -162,7 +163,7 @@ class ASTToQMODCode(ast.NodeVisitor):
|
|
162
163
|
def generic_visit(self, node: ast.AST) -> None:
|
163
164
|
raise AssertionError("Cannot parse node of type: " + type(node).__name__)
|
164
165
|
|
165
|
-
def indent_items(self, items: Callable[[],
|
166
|
+
def indent_items(self, items: Callable[[], list[str]]) -> str:
|
166
167
|
should_indent = (
|
167
168
|
len("".join([i.strip() for i in items()])) >= LIST_FORMAT_CHAR_LIMIT
|
168
169
|
)
|
@@ -188,8 +189,8 @@ class ASTToQMODCode(ast.NodeVisitor):
|
|
188
189
|
def _remove_redundant_parentheses(expr: str) -> str:
|
189
190
|
if not (expr.startswith("(") and expr.endswith(")")):
|
190
191
|
return expr
|
191
|
-
parentheses_map:
|
192
|
-
stack:
|
192
|
+
parentheses_map: dict[int, int] = dict()
|
193
|
+
stack: list[int] = []
|
193
194
|
for index, char in enumerate(expr):
|
194
195
|
if char == "(":
|
195
196
|
stack.append(index)
|
@@ -208,8 +209,8 @@ def _remove_redundant_parentheses(expr: str) -> str:
|
|
208
209
|
|
209
210
|
def transform_expression(
|
210
211
|
expr: str,
|
211
|
-
imports:
|
212
|
-
symbolic_imports:
|
212
|
+
imports: dict[str, int],
|
213
|
+
symbolic_imports: dict[str, int],
|
213
214
|
level: int = 0,
|
214
215
|
decimal_precision: int = DEFAULT_DECIMAL_PRECISION,
|
215
216
|
) -> str:
|
@@ -1,4 +1,5 @@
|
|
1
|
-
from
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import Optional, Union, cast
|
2
3
|
|
3
4
|
import black
|
4
5
|
|
@@ -49,9 +50,6 @@ from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
49
50
|
ArithmeticOperation,
|
50
51
|
ArithmeticOperationKind,
|
51
52
|
)
|
52
|
-
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
53
|
-
QuantumAssignmentOperation,
|
54
|
-
)
|
55
53
|
from classiq.interface.model.quantum_function_call import (
|
56
54
|
OperandIdentifier,
|
57
55
|
QuantumFunctionCall,
|
@@ -88,20 +86,20 @@ class VariableDeclarationAssignment(Visitor):
|
|
88
86
|
def __init__(self, pretty_printer: "PythonPrettyPrinter") -> None:
|
89
87
|
self.pretty_printer = pretty_printer
|
90
88
|
|
91
|
-
def visit(self, node: NodeType) ->
|
89
|
+
def visit(self, node: NodeType) -> tuple[str, Optional[list[str]]]:
|
92
90
|
res = super().visit(node)
|
93
91
|
if not isinstance(res, tuple):
|
94
92
|
raise AssertionError(f"Pretty printing for {type(node)} is not supported ")
|
95
93
|
return res # type: ignore[return-value]
|
96
94
|
|
97
|
-
def visit_QuantumBit(self, qtype: QuantumBit) ->
|
95
|
+
def visit_QuantumBit(self, qtype: QuantumBit) -> tuple[str, Optional[list[str]]]:
|
98
96
|
self.pretty_printer._imports["QBit"] = 1
|
99
97
|
|
100
98
|
return "QBit", None
|
101
99
|
|
102
100
|
def visit_QuantumBitvector(
|
103
101
|
self, qtype: QuantumBitvector
|
104
|
-
) ->
|
102
|
+
) -> tuple[str, Optional[list[str]]]:
|
105
103
|
self.pretty_printer._imports["QArray"] = 1
|
106
104
|
|
107
105
|
element_type = self.pretty_printer.visit(qtype.element_type)
|
@@ -111,7 +109,7 @@ class VariableDeclarationAssignment(Visitor):
|
|
111
109
|
|
112
110
|
def visit_QuantumNumeric(
|
113
111
|
self, qtype: QuantumNumeric
|
114
|
-
) ->
|
112
|
+
) -> tuple[str, Optional[list[str]]]:
|
115
113
|
self.pretty_printer._imports["QNum"] = 1
|
116
114
|
|
117
115
|
params = []
|
@@ -124,7 +122,7 @@ class VariableDeclarationAssignment(Visitor):
|
|
124
122
|
|
125
123
|
return "QNum", params
|
126
124
|
|
127
|
-
def visit_TypeName(self, qtype: TypeName) ->
|
125
|
+
def visit_TypeName(self, qtype: TypeName) -> tuple[str, None]:
|
128
126
|
return qtype.name, None
|
129
127
|
|
130
128
|
|
@@ -136,7 +134,7 @@ class PythonPrettyPrinter(Visitor):
|
|
136
134
|
self._import_enum = False
|
137
135
|
self._import_dataclass = False
|
138
136
|
self._import_annotated = False
|
139
|
-
self._symbolic_imports:
|
137
|
+
self._symbolic_imports: dict[str, int] = dict()
|
140
138
|
self._functions: Optional[Mapping[str, QuantumFunctionDeclaration]] = None
|
141
139
|
|
142
140
|
def visit(self, node: NodeType) -> str:
|
@@ -183,7 +181,7 @@ class PythonPrettyPrinter(Visitor):
|
|
183
181
|
def special_imports(self) -> str:
|
184
182
|
imports = ""
|
185
183
|
if self._import_annotated:
|
186
|
-
imports += "from
|
184
|
+
imports += "from typing import Annotated\n"
|
187
185
|
if self._import_dataclass:
|
188
186
|
imports += "from dataclasses import dataclass\n"
|
189
187
|
if self._import_enum:
|
@@ -214,7 +212,7 @@ class PythonPrettyPrinter(Visitor):
|
|
214
212
|
self._import_enum = True
|
215
213
|
return f"class {enum_decl.name}(IntEnum):\n{self._visit_members(enum_decl.members)}\n"
|
216
214
|
|
217
|
-
def _visit_members(self, members:
|
215
|
+
def _visit_members(self, members: dict[str, int]) -> str:
|
218
216
|
self._level += 1
|
219
217
|
members_str = "".join(
|
220
218
|
f"{self._indent}{self.visit(member_name)} = {member_value}\n"
|
@@ -390,7 +388,10 @@ class PythonPrettyPrinter(Visitor):
|
|
390
388
|
|
391
389
|
def visit_Control(self, op: Control) -> str:
|
392
390
|
self._imports["control"] = 1
|
393
|
-
|
391
|
+
control_else = (
|
392
|
+
f", {self._visit_body(op.else_block)}" if op.else_block is not None else ""
|
393
|
+
)
|
394
|
+
return f"{self._indent}control({self.visit(op.expression)}, {self._visit_body(op.body)}{control_else})\n"
|
394
395
|
|
395
396
|
def visit_PhaseOperation(self, op: PhaseOperation) -> str:
|
396
397
|
self._imports["phase"] = 1
|
@@ -418,7 +419,7 @@ class PythonPrettyPrinter(Visitor):
|
|
418
419
|
return f"{self._indent}invert({self._visit_body(invert.body)})\n"
|
419
420
|
|
420
421
|
def _visit_body(
|
421
|
-
self, body: StatementBlock, operand_arguments: Optional[
|
422
|
+
self, body: StatementBlock, operand_arguments: Optional[list[str]] = None
|
422
423
|
) -> str:
|
423
424
|
if len(body) == 0:
|
424
425
|
return "lambda: []"
|
@@ -428,13 +429,16 @@ class PythonPrettyPrinter(Visitor):
|
|
428
429
|
code = f"lambda{argument_string}: {'[' if len(body) > 1 else ''}\n"
|
429
430
|
self._level += 1
|
430
431
|
for i, statement in enumerate(body):
|
431
|
-
if isinstance(
|
432
|
-
statement, (QuantumAssignmentOperation, VariableDeclarationStatement)
|
433
|
-
):
|
432
|
+
if isinstance(statement, VariableDeclarationStatement):
|
434
433
|
raise AssertionError(
|
435
|
-
"pretty printing
|
434
|
+
"pretty printing variable declaration statements in quantum lambda function is unsupported."
|
436
435
|
)
|
437
|
-
|
436
|
+
if isinstance(statement, AmplitudeLoadingOperation):
|
437
|
+
code += self.visit_AmplitudeLoadingOperation(statement, in_lambda=True)
|
438
|
+
elif isinstance(statement, ArithmeticOperation):
|
439
|
+
code += self.visit_ArithmeticOperation(statement, in_lambda=True)
|
440
|
+
else:
|
441
|
+
code += self.visit(statement)
|
438
442
|
if i < len(body) - 1:
|
439
443
|
code += ","
|
440
444
|
self._level -= 1
|
@@ -454,7 +458,7 @@ class PythonPrettyPrinter(Visitor):
|
|
454
458
|
)
|
455
459
|
|
456
460
|
def visit_QuantumLambdaFunction(self, qlambda: QuantumLambdaFunction) -> str:
|
457
|
-
return self._visit_body(qlambda.body, qlambda.
|
461
|
+
return self._visit_body(qlambda.body, qlambda.pos_rename_params)
|
458
462
|
|
459
463
|
def visit_HandleBinding(self, var_ref: HandleBinding) -> str:
|
460
464
|
return var_ref.name
|
@@ -468,21 +472,32 @@ class PythonPrettyPrinter(Visitor):
|
|
468
472
|
def visit_FieldHandleBinding(self, var_ref: FieldHandleBinding) -> str:
|
469
473
|
return f"{self.visit(var_ref.base_handle)}.{self.visit(var_ref.field)}"
|
470
474
|
|
471
|
-
def visit_ArithmeticOperation(
|
475
|
+
def visit_ArithmeticOperation(
|
476
|
+
self, arith_op: ArithmeticOperation, in_lambda: bool = False
|
477
|
+
) -> str:
|
472
478
|
if arith_op.operation_kind == ArithmeticOperationKind.Assignment:
|
473
479
|
op = "|="
|
480
|
+
func = "assign"
|
474
481
|
elif arith_op.operation_kind == ArithmeticOperationKind.InplaceXor:
|
475
482
|
op = "^="
|
483
|
+
func = "inplace_xor"
|
476
484
|
else:
|
477
485
|
op = "+="
|
486
|
+
func = "inplace_add"
|
487
|
+
if in_lambda:
|
488
|
+
self._imports[func] = 1
|
489
|
+
return f"{func}({self.visit(arith_op.expression)}, {self._indent}{self.visit(arith_op.result_var)})\n"
|
478
490
|
return f"{self._indent}{self.visit(arith_op.result_var)} {op} {self.visit(arith_op.expression)}\n"
|
479
491
|
|
480
492
|
def visit_AmplitudeLoadingOperation(
|
481
|
-
self, amplitude_loading_op: AmplitudeLoadingOperation
|
493
|
+
self, amplitude_loading_op: AmplitudeLoadingOperation, in_lambda: bool = False
|
482
494
|
) -> str:
|
495
|
+
if in_lambda:
|
496
|
+
self._imports["assign_amplitude"] = 1
|
497
|
+
return f"assign_amplitude({self.visit(amplitude_loading_op.expression)}, {self._indent}{self.visit(amplitude_loading_op.result_var)})\n"
|
483
498
|
return f"{self._indent}{self.visit(amplitude_loading_op.result_var)} *= {self.visit(amplitude_loading_op.expression)}\n"
|
484
499
|
|
485
|
-
def _print_bind_handles(self, handles:
|
500
|
+
def _print_bind_handles(self, handles: list[HandleBinding]) -> str:
|
486
501
|
if len(handles) == 1:
|
487
502
|
return self.visit(handles[0])
|
488
503
|
|
@@ -26,6 +26,11 @@ if sys.version_info[0:2] >= (3, 9):
|
|
26
26
|
pass
|
27
27
|
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
28
28
|
|
29
|
+
CARRAY_ERROR_MESSAGE = (
|
30
|
+
"CArray accepts one or two generic parameters in the form "
|
31
|
+
"`CArray[<element-type>]` or `CArray[<element-type>, <size>]`"
|
32
|
+
)
|
33
|
+
|
29
34
|
|
30
35
|
class PythonClassicalType:
|
31
36
|
def convert(self, py_type: type) -> Optional[ConcreteClassicalType]:
|
@@ -48,16 +53,15 @@ class PythonClassicalType:
|
|
48
53
|
element_type=self.convert(array_args[0]),
|
49
54
|
size=get_type_hint_expr(array_args[1]),
|
50
55
|
)
|
51
|
-
raise ClassiqValueError(
|
52
|
-
"CArray accepts one or two generic parameters in the form "
|
53
|
-
"`CArray[<element-type>]` or `CArray[<element-type>, <size>]`"
|
54
|
-
)
|
56
|
+
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
55
57
|
elif inspect.isclass(py_type) and dataclasses.is_dataclass(py_type):
|
56
58
|
self.register_struct(py_type)
|
57
59
|
return Struct(name=py_type.__name__)
|
58
60
|
elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
|
59
61
|
self.register_enum(py_type)
|
60
62
|
return Enum(name=py_type.__name__)
|
63
|
+
elif py_type in (CArray, list):
|
64
|
+
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
61
65
|
return None
|
62
66
|
|
63
67
|
def register_struct(self, py_type: type) -> None:
|
classiq/qmod/qfunc.py
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
from typing import Callable,
|
1
|
+
from typing import Callable, Literal, Optional, Union, overload
|
2
2
|
|
3
3
|
from classiq.qmod.quantum_callable import QCallable
|
4
4
|
from classiq.qmod.quantum_function import ExternalQFunc, GenerativeQFunc, QFunc
|
5
5
|
|
6
|
-
GEN_QFUNCS:
|
7
|
-
DEC_QFUNCS:
|
6
|
+
GEN_QFUNCS: list[GenerativeQFunc] = []
|
7
|
+
DEC_QFUNCS: list[QFunc] = []
|
8
8
|
|
9
9
|
|
10
10
|
def set_discovered_functions(
|
11
|
-
dec_funcs:
|
11
|
+
dec_funcs: list[QFunc], gen_funcs: list[GenerativeQFunc]
|
12
12
|
) -> None:
|
13
13
|
DEC_QFUNCS.clear()
|
14
14
|
DEC_QFUNCS.extend(dec_funcs)
|