classiq 0.37.1__py3-none-any.whl → 0.65.3__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 +49 -34
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +3 -2
- classiq/_analyzer_extras/interactive_hardware.py +3 -3
- classiq/_internals/api_wrapper.py +241 -95
- classiq/_internals/async_utils.py +2 -77
- classiq/_internals/authentication/auth0.py +26 -10
- classiq/_internals/authentication/authentication.py +11 -0
- classiq/_internals/authentication/device.py +18 -8
- classiq/_internals/authentication/password_manager.py +40 -13
- classiq/_internals/authentication/token_manager.py +11 -6
- classiq/_internals/client.py +106 -37
- classiq/_internals/config.py +3 -4
- classiq/_internals/host_checker.py +38 -15
- classiq/_internals/jobs.py +56 -50
- classiq/_internals/type_validation.py +9 -9
- classiq/analyzer/__init__.py +1 -3
- classiq/analyzer/analyzer.py +50 -47
- classiq/analyzer/analyzer_utilities.py +15 -15
- classiq/analyzer/rb.py +19 -20
- classiq/analyzer/show_interactive_hack.py +30 -7
- classiq/analyzer/url_utils.py +2 -3
- classiq/applications/__init__.py +3 -12
- classiq/applications/chemistry/__init__.py +14 -10
- classiq/applications/chemistry/ansatz_parameters.py +4 -4
- classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +170 -170
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/applications/combinatorial_helpers/allowed_constraints.py +23 -0
- classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
- classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +166 -0
- classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
- classiq/applications/combinatorial_helpers/encoding_utils.py +124 -0
- classiq/applications/combinatorial_helpers/memory.py +75 -0
- classiq/applications/combinatorial_helpers/optimization_model.py +193 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
- classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
- classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
- classiq/applications/combinatorial_helpers/transformations/encoding.py +189 -0
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +143 -0
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +120 -0
- classiq/applications/combinatorial_helpers/transformations/penalty.py +31 -0
- classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
- classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +74 -0
- classiq/applications/combinatorial_helpers/transformations/slack_variables.py +87 -0
- classiq/applications/combinatorial_optimization/__init__.py +24 -5
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +137 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
- classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
- classiq/applications/finance/__init__.py +4 -5
- classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +50 -57
- classiq/applications/grover/__init__.py +9 -0
- classiq/applications/grover/grover_model_constructor.py +157 -0
- classiq/applications/hamiltonian/__init__.py +0 -0
- classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
- classiq/applications/libraries/__init__.py +0 -0
- classiq/applications/libraries/qmci_library.py +22 -0
- classiq/applications/qnn/__init__.py +2 -4
- classiq/applications/qnn/circuit_utils.py +8 -8
- classiq/applications/qnn/datasets/__init__.py +9 -11
- classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
- classiq/applications/qnn/datasets/dataset_not.py +2 -1
- classiq/applications/qnn/datasets/dataset_parity.py +2 -2
- classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
- classiq/applications/qnn/qlayer.py +30 -10
- classiq/applications/qnn/torch_utils.py +4 -3
- classiq/applications/qnn/types.py +7 -7
- classiq/applications/qsvm/__init__.py +6 -4
- classiq/applications/qsvm/qsvm.py +4 -10
- classiq/applications/qsvm/qsvm_data_generation.py +5 -8
- classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
- classiq/execution/__init__.py +8 -3
- classiq/execution/all_hardware_devices.py +11 -0
- classiq/execution/execution_session.py +400 -0
- classiq/execution/iqcc.py +63 -0
- classiq/execution/jobs.py +197 -25
- classiq/execution/qnn.py +79 -0
- classiq/executor.py +23 -117
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +49 -16
- classiq/interface/analyzer/cytoscape_graph.py +15 -9
- classiq/interface/analyzer/result.py +36 -32
- classiq/interface/applications/qsvm.py +28 -25
- classiq/interface/ast_node.py +16 -0
- classiq/interface/backend/backend_preferences.py +390 -119
- classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
- classiq/interface/backend/pydantic_backend.py +27 -22
- classiq/interface/backend/quantum_backend_providers.py +70 -16
- classiq/interface/chemistry/fermionic_operator.py +43 -32
- classiq/interface/chemistry/ground_state_problem.py +42 -24
- classiq/interface/chemistry/molecule.py +20 -14
- classiq/interface/chemistry/operator.py +75 -236
- classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +2 -4
- classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
- 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/mds.py +2 -1
- classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
- classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
- classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
- classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
- classiq/interface/combinatorial_optimization/examples/set_cover.py +3 -3
- classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +14 -9
- classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
- classiq/interface/combinatorial_optimization/result.py +1 -3
- classiq/interface/combinatorial_optimization/solver_types.py +1 -1
- classiq/interface/debug_info/__init__.py +0 -0
- classiq/interface/debug_info/debug_info.py +86 -0
- classiq/interface/exceptions.py +201 -0
- classiq/interface/execution/iqcc.py +19 -0
- classiq/interface/execution/jobs.py +15 -12
- classiq/interface/execution/primitives.py +18 -0
- classiq/interface/executor/constants.py +1 -0
- classiq/interface/executor/estimation.py +2 -2
- classiq/interface/executor/execution_preferences.py +26 -143
- classiq/interface/executor/execution_request.py +36 -56
- classiq/interface/executor/execution_result.py +30 -8
- classiq/interface/executor/iqae_result.py +4 -6
- classiq/interface/executor/optimizer_preferences.py +34 -22
- classiq/interface/executor/{quantum_program.py → quantum_code.py} +44 -34
- classiq/interface/executor/quantum_instruction_set.py +3 -2
- classiq/interface/executor/register_initialization.py +12 -17
- classiq/interface/executor/result.py +122 -64
- classiq/interface/executor/vqe_result.py +11 -11
- classiq/interface/finance/function_input.py +42 -19
- classiq/interface/finance/gaussian_model_input.py +7 -5
- classiq/interface/finance/log_normal_model_input.py +6 -4
- classiq/interface/finance/model_input.py +6 -4
- classiq/interface/generator/adjacency.py +1 -3
- classiq/interface/generator/amplitude_loading.py +27 -14
- classiq/interface/generator/ansatz_library.py +5 -5
- classiq/interface/generator/application_apis/__init__.py +1 -0
- classiq/interface/generator/application_apis/arithmetic_declarations.py +17 -0
- classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
- classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
- classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
- classiq/interface/generator/application_apis/finance_declarations.py +48 -69
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
- classiq/interface/generator/arith/argument_utils.py +57 -6
- classiq/interface/generator/arith/arithmetic.py +37 -16
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +15 -17
- classiq/interface/generator/arith/arithmetic_expression_abc.py +70 -26
- classiq/interface/generator/arith/arithmetic_expression_parser.py +18 -12
- classiq/interface/generator/arith/arithmetic_expression_validator.py +61 -43
- classiq/interface/generator/arith/arithmetic_operations.py +19 -16
- classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
- classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
- classiq/interface/generator/arith/ast_node_rewrite.py +4 -3
- classiq/interface/generator/arith/binary_ops.py +375 -139
- classiq/interface/generator/arith/endianness.py +1 -1
- classiq/interface/generator/arith/extremum_operations.py +96 -23
- classiq/interface/generator/arith/logical_ops.py +16 -12
- classiq/interface/generator/arith/machine_precision.py +3 -0
- classiq/interface/generator/arith/number_utils.py +44 -48
- classiq/interface/generator/arith/register_user_input.py +70 -27
- classiq/interface/generator/arith/unary_ops.py +57 -46
- classiq/interface/generator/arith/uncomputation_methods.py +1 -1
- classiq/interface/generator/builtin_api_builder.py +2 -9
- classiq/interface/generator/chemistry_function_params.py +5 -5
- classiq/interface/generator/circuit_code/circuit_code.py +7 -7
- classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
- classiq/interface/generator/commuting_pauli_exponentiation.py +8 -6
- classiq/interface/generator/compiler_keywords.py +8 -0
- classiq/interface/generator/complex_type.py +13 -25
- classiq/interface/generator/constant.py +3 -4
- classiq/interface/generator/control_state.py +35 -28
- classiq/interface/generator/copy.py +47 -0
- classiq/interface/generator/custom_ansatz.py +2 -5
- classiq/interface/generator/distance.py +3 -5
- classiq/interface/generator/excitations.py +3 -2
- classiq/interface/generator/expressions/atomic_expression_functions.py +26 -8
- classiq/interface/generator/expressions/enums/__init__.py +0 -10
- classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
- classiq/interface/generator/expressions/evaluated_expression.py +21 -7
- classiq/interface/generator/expressions/expression.py +27 -15
- classiq/interface/generator/expressions/expression_constants.py +9 -3
- classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +59 -0
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
- classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
- classiq/interface/generator/expressions/sympy_supported_expressions.py +20 -11
- classiq/interface/generator/finance.py +3 -3
- classiq/interface/generator/function_param_library.py +6 -6
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
- classiq/interface/generator/function_params.py +42 -69
- classiq/interface/generator/functions/__init__.py +0 -22
- classiq/interface/generator/functions/builtins/__init__.py +0 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
- classiq/interface/generator/functions/classical_function_declaration.py +18 -9
- classiq/interface/generator/functions/classical_type.py +47 -166
- classiq/interface/generator/functions/concrete_types.py +55 -0
- classiq/interface/generator/functions/function_declaration.py +13 -14
- classiq/interface/generator/functions/port_declaration.py +1 -13
- classiq/interface/generator/functions/qmod_python_interface.py +2 -1
- classiq/interface/generator/functions/type_name.py +90 -0
- classiq/interface/generator/generated_circuit_data.py +155 -22
- classiq/interface/generator/grover_diffuser.py +32 -25
- classiq/interface/generator/grover_operator.py +34 -23
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +12 -8
- classiq/interface/generator/hardware/hardware_data.py +76 -36
- classiq/interface/generator/hardware_efficient_ansatz.py +38 -17
- classiq/interface/generator/hartree_fock.py +14 -4
- classiq/interface/generator/identity.py +10 -6
- classiq/interface/generator/linear_pauli_rotations.py +33 -19
- classiq/interface/generator/mcmt_method.py +1 -1
- classiq/interface/generator/mcu.py +20 -16
- classiq/interface/generator/mcx.py +29 -20
- classiq/interface/generator/model/__init__.py +2 -5
- classiq/interface/generator/model/constraints.py +27 -8
- classiq/interface/generator/model/model.py +32 -203
- classiq/interface/generator/model/preferences/preferences.py +118 -43
- classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +27 -22
- classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
- classiq/interface/generator/oracles/custom_oracle.py +17 -13
- classiq/interface/generator/oracles/oracle_abc.py +9 -9
- classiq/interface/generator/partitioned_register.py +7 -7
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
- classiq/interface/generator/preferences/optimization.py +1 -2
- classiq/interface/generator/qpe.py +47 -34
- classiq/interface/generator/qsvm.py +13 -17
- classiq/interface/generator/quantum_function_call.py +107 -87
- classiq/interface/generator/{generated_circuit.py → quantum_program.py} +50 -37
- classiq/interface/generator/range_types.py +13 -12
- classiq/interface/generator/register_role.py +18 -6
- classiq/interface/generator/slice_parsing_utils.py +11 -6
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +32 -39
- classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
- classiq/interface/generator/standard_gates/standard_gates.py +3 -3
- classiq/interface/generator/standard_gates/u_gate.py +7 -10
- classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
- classiq/interface/generator/state_preparation/distributions.py +16 -15
- classiq/interface/generator/state_preparation/metrics.py +5 -7
- classiq/interface/generator/state_preparation/state_preparation.py +30 -23
- classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
- classiq/interface/generator/transpiler_basis_gates.py +7 -3
- classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
- classiq/interface/generator/types/compilation_metadata.py +6 -0
- classiq/interface/generator/types/enum_declaration.py +54 -0
- classiq/interface/generator/types/qstruct_declaration.py +18 -0
- classiq/interface/generator/types/struct_declaration.py +15 -14
- classiq/interface/generator/ucc.py +9 -6
- classiq/interface/generator/unitary_gate.py +10 -6
- classiq/interface/generator/user_defined_function_params.py +4 -1
- classiq/interface/generator/validations/flow_graph.py +11 -9
- classiq/interface/generator/validations/validator_functions.py +8 -6
- classiq/interface/generator/visitor.py +23 -16
- classiq/interface/hardware.py +31 -10
- classiq/interface/helpers/classproperty.py +8 -0
- classiq/interface/helpers/custom_encoders.py +3 -0
- classiq/interface/helpers/custom_pydantic_types.py +40 -50
- classiq/interface/helpers/datastructures.py +26 -0
- 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 +7 -11
- classiq/interface/helpers/validation_helpers.py +4 -21
- classiq/interface/helpers/versioned_model.py +1 -1
- classiq/interface/ide/ide_data.py +16 -20
- classiq/interface/ide/visual_model.py +130 -0
- classiq/interface/interface_version.py +1 -0
- classiq/interface/jobs.py +35 -6
- classiq/interface/model/allocate.py +16 -0
- classiq/interface/model/bind_operation.py +44 -14
- classiq/interface/model/classical_if.py +15 -0
- classiq/interface/model/classical_parameter_declaration.py +33 -3
- classiq/interface/model/control.py +45 -0
- classiq/interface/model/handle_binding.py +298 -20
- classiq/interface/model/inplace_binary_operation.py +31 -26
- classiq/interface/model/invert.py +12 -0
- classiq/interface/model/model.py +87 -73
- classiq/interface/model/native_function_definition.py +16 -21
- classiq/interface/model/parameter.py +13 -0
- classiq/interface/model/phase_operation.py +11 -0
- classiq/interface/model/port_declaration.py +27 -9
- classiq/interface/model/power.py +14 -0
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +38 -21
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
- classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
- classiq/interface/model/quantum_function_call.py +146 -462
- classiq/interface/model/quantum_function_declaration.py +193 -152
- classiq/interface/model/quantum_lambda_function.py +65 -0
- classiq/interface/model/quantum_statement.py +71 -12
- classiq/interface/model/quantum_type.py +205 -67
- classiq/interface/model/quantum_variable_declaration.py +4 -26
- classiq/interface/model/repeat.py +15 -0
- classiq/interface/model/statement_block.py +58 -0
- classiq/interface/model/validation_handle.py +13 -6
- classiq/interface/model/variable_declaration_statement.py +3 -1
- classiq/interface/model/within_apply_operation.py +13 -0
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
- classiq/interface/server/global_versions.py +6 -7
- classiq/interface/server/routes.py +22 -21
- classiq/interface/source_reference.py +59 -0
- classiq/model_expansions/__init__.py +0 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
- classiq/model_expansions/capturing/__init__.py +0 -0
- classiq/model_expansions/capturing/captured_vars.py +435 -0
- classiq/model_expansions/capturing/mangling_utils.py +56 -0
- classiq/model_expansions/closure.py +171 -0
- classiq/model_expansions/debug_flag.py +3 -0
- classiq/model_expansions/evaluators/__init__.py +0 -0
- classiq/model_expansions/evaluators/arg_type_match.py +158 -0
- classiq/model_expansions/evaluators/argument_types.py +42 -0
- classiq/model_expansions/evaluators/classical_expression.py +36 -0
- classiq/model_expansions/evaluators/control.py +144 -0
- classiq/model_expansions/evaluators/parameter_types.py +226 -0
- classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
- classiq/model_expansions/evaluators/type_type_match.py +90 -0
- classiq/model_expansions/expression_evaluator.py +135 -0
- classiq/model_expansions/expression_renamer.py +76 -0
- classiq/model_expansions/function_builder.py +247 -0
- classiq/model_expansions/generative_functions.py +158 -0
- classiq/model_expansions/interpreters/__init__.py +0 -0
- classiq/model_expansions/interpreters/base_interpreter.py +263 -0
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
- classiq/model_expansions/model_tables.py +18 -0
- classiq/model_expansions/quantum_operations/__init__.py +9 -0
- classiq/model_expansions/quantum_operations/bind.py +60 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
- classiq/model_expansions/quantum_operations/classicalif.py +53 -0
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
- classiq/model_expansions/quantum_operations/emitter.py +181 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
- classiq/model_expansions/quantum_operations/repeat.py +56 -0
- classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
- classiq/model_expansions/scope.py +240 -0
- classiq/model_expansions/scope_initialization.py +150 -0
- classiq/model_expansions/sympy_conversion/__init__.py +0 -0
- classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
- classiq/model_expansions/transformers/__init__.py +0 -0
- classiq/model_expansions/transformers/ast_renamer.py +26 -0
- classiq/model_expansions/transformers/var_splitter.py +299 -0
- classiq/model_expansions/utils/__init__.py +0 -0
- classiq/model_expansions/utils/counted_name_allocator.py +11 -0
- classiq/model_expansions/utils/handles_collector.py +33 -0
- classiq/model_expansions/visitors/__init__.py +0 -0
- classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
- classiq/model_expansions/visitors/variable_references.py +144 -0
- classiq/open_library/__init__.py +4 -0
- classiq/open_library/functions/__init__.py +130 -0
- classiq/open_library/functions/amplitude_estimation.py +30 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
- classiq/open_library/functions/grover.py +157 -0
- classiq/open_library/functions/hea.py +115 -0
- classiq/open_library/functions/linear_pauli_rotation.py +82 -0
- classiq/open_library/functions/modular_exponentiation.py +201 -0
- classiq/open_library/functions/qaoa_penalty.py +117 -0
- classiq/open_library/functions/qft_functions.py +54 -0
- classiq/open_library/functions/qpe.py +46 -0
- classiq/open_library/functions/qsvt.py +331 -0
- classiq/open_library/functions/state_preparation.py +301 -0
- classiq/open_library/functions/swap_test.py +27 -0
- classiq/open_library/functions/utility_functions.py +81 -0
- classiq/open_library/functions/variational.py +52 -0
- classiq/qmod/__init__.py +17 -10
- classiq/qmod/builtins/__init__.py +19 -2
- classiq/qmod/builtins/classical_execution_primitives.py +60 -47
- classiq/qmod/builtins/classical_functions.py +44 -38
- classiq/qmod/builtins/constants.py +10 -0
- classiq/qmod/builtins/enums.py +208 -0
- classiq/qmod/builtins/functions/__init__.py +137 -0
- classiq/qmod/builtins/functions/allocation.py +150 -0
- classiq/qmod/builtins/functions/arithmetic.py +55 -0
- classiq/qmod/builtins/functions/benchmarking.py +8 -0
- classiq/qmod/builtins/functions/chemistry.py +91 -0
- classiq/qmod/builtins/functions/exponentiation.py +105 -0
- classiq/qmod/builtins/functions/finance.py +34 -0
- classiq/qmod/builtins/functions/operators.py +16 -0
- classiq/qmod/builtins/functions/qsvm.py +24 -0
- classiq/qmod/builtins/functions/standard_gates.py +651 -0
- classiq/qmod/builtins/operations.py +379 -57
- classiq/qmod/builtins/structs.py +103 -80
- classiq/qmod/cfunc.py +42 -0
- classiq/qmod/classical_function.py +8 -20
- classiq/qmod/cparam.py +64 -0
- classiq/qmod/create_model_function.py +56 -0
- classiq/qmod/declaration_inferrer.py +145 -112
- classiq/qmod/expression_query.py +39 -0
- classiq/qmod/generative.py +42 -0
- classiq/qmod/model_state_container.py +19 -5
- classiq/qmod/native/__init__.py +7 -0
- classiq/qmod/native/expression_to_qmod.py +194 -0
- classiq/qmod/native/pretty_printer.py +401 -0
- classiq/qmod/pretty_print/__init__.py +7 -0
- classiq/qmod/pretty_print/expression_to_python.py +222 -0
- classiq/qmod/pretty_print/pretty_printer.py +572 -0
- classiq/qmod/python_classical_type.py +67 -0
- classiq/qmod/qfunc.py +79 -0
- classiq/qmod/qmod_constant.py +143 -0
- classiq/qmod/qmod_parameter.py +84 -53
- classiq/qmod/qmod_variable.py +497 -100
- classiq/qmod/quantum_callable.py +17 -7
- classiq/qmod/quantum_expandable.py +278 -105
- classiq/qmod/quantum_function.py +232 -48
- classiq/qmod/semantics/__init__.py +0 -0
- classiq/qmod/semantics/annotation/__init__.py +0 -0
- classiq/qmod/semantics/annotation/call_annotation.py +92 -0
- classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
- classiq/qmod/semantics/error_manager.py +88 -0
- classiq/qmod/semantics/lambdas.py +25 -0
- classiq/qmod/semantics/static_semantics_visitor.py +384 -0
- classiq/qmod/semantics/validation/__init__.py +0 -0
- classiq/qmod/semantics/validation/constants_validation.py +16 -0
- classiq/qmod/semantics/validation/func_call_validation.py +99 -0
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
- classiq/qmod/semantics/validation/handle_validation.py +85 -0
- classiq/qmod/semantics/validation/main_validation.py +33 -0
- classiq/qmod/semantics/validation/types_validation.py +128 -0
- classiq/qmod/symbolic.py +178 -111
- classiq/qmod/symbolic_expr.py +36 -12
- classiq/qmod/symbolic_type.py +2 -5
- classiq/qmod/type_attribute_remover.py +32 -0
- classiq/qmod/utilities.py +108 -1
- classiq/qmod/write_qmod.py +53 -0
- classiq/synthesis.py +210 -22
- {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -8
- classiq-0.65.3.dist-info/RECORD +521 -0
- {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/WHEEL +1 -1
- classiq/_internals/_qfunc_ext.py +0 -6
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -17
- classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
- classiq/applications_model_constructors/grover_model_constructor.py +0 -227
- classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
- classiq/builtin_functions/__init__.py +0 -43
- classiq/builtin_functions/amplitude_loading.py +0 -3
- classiq/builtin_functions/binary_ops.py +0 -1
- classiq/builtin_functions/exponentiation.py +0 -5
- classiq/builtin_functions/qpe.py +0 -4
- classiq/builtin_functions/qsvm.py +0 -7
- classiq/builtin_functions/range_types.py +0 -5
- classiq/builtin_functions/standard_gates.py +0 -1
- classiq/builtin_functions/state_preparation.py +0 -6
- classiq/builtin_functions/suzuki_trotter.py +0 -3
- classiq/exceptions.py +0 -131
- classiq/interface/executor/aws_execution_cost.py +0 -72
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/credit_risk_example/linear_gci.py +0 -115
- classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -59
- classiq/interface/generator/expressions/enums/chemistry.py +0 -28
- classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
- classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
- classiq/interface/generator/expressions/enums/optimizers.py +0 -9
- classiq/interface/generator/expressions/enums/pauli.py +0 -8
- classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
- classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -862
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
- classiq/interface/generator/functions/foreign_function_definition.py +0 -106
- classiq/interface/generator/functions/function_implementation.py +0 -103
- classiq/interface/generator/functions/native_function_definition.py +0 -153
- classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
- classiq/interface/generator/functions/register.py +0 -42
- classiq/interface/generator/functions/register_mapping_data.py +0 -102
- classiq/interface/generator/inequality_mixer.py +0 -51
- classiq/interface/generator/model/classical_main_validator.py +0 -106
- classiq/interface/generator/range_mixer.py +0 -56
- classiq/interface/generator/state_propagator.py +0 -63
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -2
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
- classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
- classiq/interface/generator/types/combinatorial_problem.py +0 -26
- classiq/interface/ide/show.py +0 -34
- classiq/interface/model/common_model_types.py +0 -23
- classiq/interface/model/numeric_reinterpretation.py +0 -25
- classiq/interface/model/operator_synthesis_data.py +0 -48
- classiq/interface/model/quantum_expressions/control_state.py +0 -38
- classiq/interface/model/quantum_if_operation.py +0 -95
- classiq/interface/model/resolvers/function_call_resolver.py +0 -43
- classiq/interface/model/validations/handle_validation_base.py +0 -55
- classiq/interface/model/validations/handles_validator.py +0 -154
- classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
- classiq/model/__init__.py +0 -14
- classiq/model/composite_function_generator.py +0 -33
- classiq/model/function_handler.py +0 -466
- classiq/model/function_handler.pyi +0 -152
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -246
- classiq/qmod/builtins/functions.py +0 -896
- classiq/qmod/qmod_struct.py +0 -37
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -207
- classiq/quantum_functions/decorators.py +0 -22
- classiq/quantum_functions/function_library.py +0 -181
- classiq/quantum_functions/function_parser.py +0 -74
- classiq/quantum_functions/quantum_function.py +0 -236
- classiq-0.37.1.dist-info/RECORD +0 -418
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
- /classiq/{interface/generator/credit_risk_example → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/pauli_helpers}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/py.typed} +0 -0
- /classiq/{interface/model/resolvers → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
- /classiq/{interface/model/validations → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
- /classiq/{_internals → interface}/enum_utils.py +0 -0
@@ -0,0 +1,435 @@
|
|
1
|
+
import dataclasses
|
2
|
+
from collections.abc import Sequence
|
3
|
+
from dataclasses import dataclass, field
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
5
|
+
|
6
|
+
from classiq.interface.enum_utils import StrEnum
|
7
|
+
from classiq.interface.exceptions import (
|
8
|
+
ClassiqExpansionError,
|
9
|
+
ClassiqInternalExpansionError,
|
10
|
+
)
|
11
|
+
from classiq.interface.generator.expressions.expression import Expression
|
12
|
+
from classiq.interface.generator.functions.port_declaration import (
|
13
|
+
PortDeclarationDirection,
|
14
|
+
)
|
15
|
+
from classiq.interface.model.handle_binding import (
|
16
|
+
HandleBinding,
|
17
|
+
NestedHandleBinding,
|
18
|
+
SlicedHandleBinding,
|
19
|
+
)
|
20
|
+
from classiq.interface.model.port_declaration import PortDeclaration
|
21
|
+
from classiq.interface.model.quantum_function_call import ArgValue
|
22
|
+
from classiq.interface.model.quantum_type import QuantumBitvector, QuantumType
|
23
|
+
from classiq.interface.model.variable_declaration_statement import (
|
24
|
+
VariableDeclarationStatement,
|
25
|
+
)
|
26
|
+
|
27
|
+
from classiq.model_expansions.capturing.mangling_utils import (
|
28
|
+
demangle_handle,
|
29
|
+
mangle_captured_var_name,
|
30
|
+
)
|
31
|
+
from classiq.model_expansions.transformers.var_splitter import SymbolPart, SymbolParts
|
32
|
+
|
33
|
+
if TYPE_CHECKING:
|
34
|
+
from classiq.model_expansions.closure import FunctionClosure
|
35
|
+
|
36
|
+
|
37
|
+
ALREADY_ALLOCATED_MESSAGE = "Cannot allocate variable '{}', it is already initialized"
|
38
|
+
ALREADY_FREED_MESSAGE = "Cannot free variable '{}', it is already uninitialized"
|
39
|
+
|
40
|
+
|
41
|
+
class PortDirection(StrEnum):
|
42
|
+
Input = "input"
|
43
|
+
Inout = "inout"
|
44
|
+
Output = "output"
|
45
|
+
Outin = "outin"
|
46
|
+
|
47
|
+
def negate(self) -> "PortDirection":
|
48
|
+
if self == PortDirection.Input:
|
49
|
+
return PortDirection.Output
|
50
|
+
if self == PortDirection.Output:
|
51
|
+
return PortDirection.Input
|
52
|
+
return self
|
53
|
+
|
54
|
+
@staticmethod
|
55
|
+
def load(direction: PortDeclarationDirection) -> "PortDirection":
|
56
|
+
if direction == PortDeclarationDirection.Input:
|
57
|
+
return PortDirection.Input
|
58
|
+
if direction == PortDeclarationDirection.Output:
|
59
|
+
return PortDirection.Output
|
60
|
+
if direction == PortDeclarationDirection.Inout:
|
61
|
+
return PortDirection.Inout
|
62
|
+
raise ClassiqInternalExpansionError
|
63
|
+
|
64
|
+
def dump(self) -> PortDeclarationDirection:
|
65
|
+
if self == PortDirection.Input:
|
66
|
+
return PortDeclarationDirection.Input
|
67
|
+
if self == PortDirection.Output:
|
68
|
+
return PortDeclarationDirection.Output
|
69
|
+
if self == PortDirection.Inout:
|
70
|
+
return PortDeclarationDirection.Inout
|
71
|
+
raise ClassiqInternalExpansionError
|
72
|
+
|
73
|
+
|
74
|
+
@dataclass(frozen=True)
|
75
|
+
class _CapturedHandle:
|
76
|
+
handle: HandleBinding
|
77
|
+
quantum_type: QuantumType
|
78
|
+
defining_function: "FunctionClosure"
|
79
|
+
direction: PortDirection
|
80
|
+
is_propagated: bool
|
81
|
+
|
82
|
+
@property
|
83
|
+
def mangled_name(self) -> str:
|
84
|
+
return mangle_captured_var_name(
|
85
|
+
self.handle.identifier,
|
86
|
+
self.defining_function.name,
|
87
|
+
self.defining_function.depth,
|
88
|
+
)
|
89
|
+
|
90
|
+
@property
|
91
|
+
def port(self) -> PortDeclaration:
|
92
|
+
return PortDeclaration(
|
93
|
+
name=self.mangled_name,
|
94
|
+
quantum_type=self.quantum_type,
|
95
|
+
direction=self.direction.dump(),
|
96
|
+
)
|
97
|
+
|
98
|
+
def is_same_var(self, other: "_CapturedHandle") -> bool:
|
99
|
+
return self.handle.name == other.handle.name and _same_closure(
|
100
|
+
self.defining_function, other.defining_function
|
101
|
+
)
|
102
|
+
|
103
|
+
def change_direction(self, new_direction: PortDirection) -> "_CapturedHandle":
|
104
|
+
return dataclasses.replace(self, direction=new_direction)
|
105
|
+
|
106
|
+
def set_propagated(self) -> "_CapturedHandle":
|
107
|
+
return dataclasses.replace(self, is_propagated=True)
|
108
|
+
|
109
|
+
def update_propagation(
|
110
|
+
self, other_captured_handle: "_CapturedHandle"
|
111
|
+
) -> "_CapturedHandle":
|
112
|
+
if self.is_propagated and not other_captured_handle.is_propagated:
|
113
|
+
return dataclasses.replace(self, is_propagated=False)
|
114
|
+
return self
|
115
|
+
|
116
|
+
def set_symbol(
|
117
|
+
self, handle: HandleBinding, quantum_type: QuantumType
|
118
|
+
) -> "_CapturedHandle":
|
119
|
+
return dataclasses.replace(self, handle=handle, quantum_type=quantum_type)
|
120
|
+
|
121
|
+
|
122
|
+
@dataclass
|
123
|
+
class CapturedVars:
|
124
|
+
_captured_handles: list[_CapturedHandle] = field(default_factory=list)
|
125
|
+
|
126
|
+
def capture_handle(
|
127
|
+
self,
|
128
|
+
handle: HandleBinding,
|
129
|
+
quantum_type: QuantumType,
|
130
|
+
defining_function: "FunctionClosure",
|
131
|
+
direction: PortDeclarationDirection,
|
132
|
+
) -> None:
|
133
|
+
self._capture_handle(
|
134
|
+
_CapturedHandle(
|
135
|
+
handle=handle,
|
136
|
+
quantum_type=quantum_type,
|
137
|
+
defining_function=defining_function,
|
138
|
+
direction=PortDirection.load(direction),
|
139
|
+
is_propagated=False,
|
140
|
+
)
|
141
|
+
)
|
142
|
+
|
143
|
+
def _capture_handle(self, captured_handle: _CapturedHandle) -> None:
|
144
|
+
if (
|
145
|
+
isinstance(captured_handle.handle, NestedHandleBinding)
|
146
|
+
and captured_handle.direction != PortDirection.Inout
|
147
|
+
):
|
148
|
+
verb = (
|
149
|
+
"free"
|
150
|
+
if captured_handle.direction == PortDirection.Input
|
151
|
+
else "allocate"
|
152
|
+
)
|
153
|
+
raise ClassiqExpansionError(
|
154
|
+
f"Cannot partially {verb} variable {captured_handle.handle.name}"
|
155
|
+
)
|
156
|
+
|
157
|
+
new_captured_handles = []
|
158
|
+
for existing_captured_handle in self._captured_handles:
|
159
|
+
if not existing_captured_handle.is_same_var(captured_handle):
|
160
|
+
new_captured_handles.append(existing_captured_handle)
|
161
|
+
continue
|
162
|
+
captured_handle = captured_handle.update_propagation(
|
163
|
+
existing_captured_handle
|
164
|
+
)
|
165
|
+
if existing_captured_handle.handle == captured_handle.handle:
|
166
|
+
captured_handle = self._conjugate_direction(
|
167
|
+
existing_captured_handle, captured_handle
|
168
|
+
)
|
169
|
+
elif captured_handle.handle.overlaps(existing_captured_handle.handle):
|
170
|
+
captured_handle = self._intersect_handles(
|
171
|
+
existing_captured_handle, captured_handle
|
172
|
+
)
|
173
|
+
else:
|
174
|
+
new_captured_handles.append(existing_captured_handle)
|
175
|
+
new_captured_handles.append(captured_handle)
|
176
|
+
self._captured_handles = new_captured_handles
|
177
|
+
|
178
|
+
def _conjugate_direction(
|
179
|
+
self,
|
180
|
+
existing_captured_handle: _CapturedHandle,
|
181
|
+
captured_handle: _CapturedHandle,
|
182
|
+
) -> _CapturedHandle:
|
183
|
+
if existing_captured_handle.direction == PortDirection.Input:
|
184
|
+
if captured_handle.direction == PortDirection.Output:
|
185
|
+
return captured_handle.change_direction(PortDirection.Inout)
|
186
|
+
if captured_handle.direction == PortDirection.Outin:
|
187
|
+
return captured_handle.change_direction(PortDirection.Input)
|
188
|
+
raise ClassiqExpansionError(
|
189
|
+
ALREADY_FREED_MESSAGE.format(captured_handle.handle)
|
190
|
+
)
|
191
|
+
if existing_captured_handle.direction == PortDirection.Output:
|
192
|
+
if captured_handle.direction == PortDirection.Input:
|
193
|
+
return captured_handle.change_direction(PortDirection.Outin)
|
194
|
+
if captured_handle.direction in (
|
195
|
+
PortDirection.Output,
|
196
|
+
PortDirection.Outin,
|
197
|
+
):
|
198
|
+
raise ClassiqExpansionError(
|
199
|
+
ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
|
200
|
+
)
|
201
|
+
return captured_handle.change_direction(PortDirection.Output)
|
202
|
+
if existing_captured_handle.direction == PortDirection.Inout:
|
203
|
+
if captured_handle.direction in (
|
204
|
+
PortDirection.Output,
|
205
|
+
PortDirection.Outin,
|
206
|
+
):
|
207
|
+
raise ClassiqExpansionError(
|
208
|
+
ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
|
209
|
+
)
|
210
|
+
elif captured_handle.direction in (
|
211
|
+
PortDirection.Input,
|
212
|
+
PortDirection.Inout,
|
213
|
+
):
|
214
|
+
raise ClassiqExpansionError(
|
215
|
+
ALREADY_FREED_MESSAGE.format(captured_handle.handle)
|
216
|
+
)
|
217
|
+
return captured_handle
|
218
|
+
|
219
|
+
def _intersect_handles(
|
220
|
+
self,
|
221
|
+
existing_captured_handle: _CapturedHandle,
|
222
|
+
captured_handle: _CapturedHandle,
|
223
|
+
) -> _CapturedHandle:
|
224
|
+
if captured_handle.handle in existing_captured_handle.handle:
|
225
|
+
if existing_captured_handle.direction in (
|
226
|
+
PortDirection.Input,
|
227
|
+
PortDirection.Outin,
|
228
|
+
):
|
229
|
+
raise ClassiqExpansionError(
|
230
|
+
ALREADY_FREED_MESSAGE.format(captured_handle.handle)
|
231
|
+
)
|
232
|
+
return existing_captured_handle
|
233
|
+
|
234
|
+
if existing_captured_handle.handle in captured_handle.handle:
|
235
|
+
if captured_handle.direction in (
|
236
|
+
PortDirection.Output,
|
237
|
+
PortDirection.Outin,
|
238
|
+
):
|
239
|
+
raise ClassiqExpansionError(
|
240
|
+
ALREADY_ALLOCATED_MESSAGE.format(captured_handle.handle)
|
241
|
+
)
|
242
|
+
return captured_handle
|
243
|
+
|
244
|
+
sliced_handle, quantum_type, other_handle = self._get_sliced_handle(
|
245
|
+
existing_captured_handle, captured_handle
|
246
|
+
)
|
247
|
+
if not isinstance(other_handle, SlicedHandleBinding):
|
248
|
+
return captured_handle.set_symbol(sliced_handle, quantum_type)
|
249
|
+
|
250
|
+
merged_handle, merged_quantum_type = self._merge_sliced_handles(
|
251
|
+
sliced_handle, other_handle, quantum_type
|
252
|
+
)
|
253
|
+
return captured_handle.set_symbol(merged_handle, merged_quantum_type)
|
254
|
+
|
255
|
+
@staticmethod
|
256
|
+
def _get_sliced_handle(
|
257
|
+
existing_captured_handle: _CapturedHandle,
|
258
|
+
captured_handle: _CapturedHandle,
|
259
|
+
) -> tuple[SlicedHandleBinding, QuantumBitvector, HandleBinding]:
|
260
|
+
handle_1 = existing_captured_handle.handle
|
261
|
+
quantum_type_1 = existing_captured_handle.quantum_type
|
262
|
+
handle_2 = captured_handle.handle
|
263
|
+
quantum_type_2 = captured_handle.quantum_type
|
264
|
+
if isinstance(handle_1, SlicedHandleBinding):
|
265
|
+
sliced_handle = handle_1
|
266
|
+
other_handle = handle_2
|
267
|
+
quantum_type = quantum_type_1
|
268
|
+
elif isinstance(handle_2, SlicedHandleBinding):
|
269
|
+
sliced_handle = handle_2
|
270
|
+
other_handle = handle_1
|
271
|
+
quantum_type = quantum_type_2
|
272
|
+
else:
|
273
|
+
raise ClassiqInternalExpansionError(
|
274
|
+
f"Unexpected overlapping handles {handle_1} and {handle_2}"
|
275
|
+
)
|
276
|
+
if not isinstance(quantum_type, QuantumBitvector):
|
277
|
+
raise ClassiqInternalExpansionError
|
278
|
+
return sliced_handle, quantum_type, other_handle
|
279
|
+
|
280
|
+
@staticmethod
|
281
|
+
def _merge_sliced_handles(
|
282
|
+
handle_1: SlicedHandleBinding,
|
283
|
+
handle_2: SlicedHandleBinding,
|
284
|
+
quantum_type: QuantumBitvector,
|
285
|
+
) -> tuple[HandleBinding, QuantumBitvector]:
|
286
|
+
if (
|
287
|
+
not handle_1.start.is_evaluated()
|
288
|
+
or not handle_1.end.is_evaluated()
|
289
|
+
or not handle_2.start.is_evaluated()
|
290
|
+
or not handle_2.end.is_evaluated()
|
291
|
+
):
|
292
|
+
raise ClassiqInternalExpansionError
|
293
|
+
|
294
|
+
new_start = min(handle_1.start.to_int_value(), handle_2.start.to_int_value())
|
295
|
+
new_end = max(handle_1.end.to_int_value(), handle_2.end.to_int_value())
|
296
|
+
merged_handle = SlicedHandleBinding(
|
297
|
+
base_handle=handle_1.base_handle,
|
298
|
+
start=Expression(expr=str(new_start)),
|
299
|
+
end=Expression(expr=str(new_end)),
|
300
|
+
)
|
301
|
+
merged_quantum_type = QuantumBitvector(
|
302
|
+
element_type=quantum_type.element_type,
|
303
|
+
length=Expression(expr=str(new_end - new_start)),
|
304
|
+
)
|
305
|
+
return merged_handle, merged_quantum_type
|
306
|
+
|
307
|
+
def update(self, other_captured_vars: "CapturedVars") -> None:
|
308
|
+
for captured_handle in other_captured_vars._captured_handles:
|
309
|
+
self._capture_handle(captured_handle)
|
310
|
+
|
311
|
+
def negate(self) -> "CapturedVars":
|
312
|
+
return CapturedVars(
|
313
|
+
_captured_handles=[
|
314
|
+
captured_handle.change_direction(captured_handle.direction.negate())
|
315
|
+
for captured_handle in self._captured_handles
|
316
|
+
]
|
317
|
+
)
|
318
|
+
|
319
|
+
def filter_vars(
|
320
|
+
self,
|
321
|
+
current_function: "FunctionClosure",
|
322
|
+
current_declarations: Optional[list[VariableDeclarationStatement]] = None,
|
323
|
+
) -> "CapturedVars":
|
324
|
+
current_declared_vars = (
|
325
|
+
None
|
326
|
+
if current_declarations is None
|
327
|
+
else {decl.name for decl in current_declarations}
|
328
|
+
)
|
329
|
+
return CapturedVars(
|
330
|
+
_captured_handles=[
|
331
|
+
captured_handle
|
332
|
+
for captured_handle in self._captured_handles
|
333
|
+
if not _same_closure(
|
334
|
+
captured_handle.defining_function, current_function
|
335
|
+
)
|
336
|
+
or (
|
337
|
+
current_declared_vars is not None
|
338
|
+
and captured_handle.handle.name not in current_declared_vars
|
339
|
+
)
|
340
|
+
]
|
341
|
+
)
|
342
|
+
|
343
|
+
def set_propagated(self) -> "CapturedVars":
|
344
|
+
return CapturedVars(
|
345
|
+
_captured_handles=[
|
346
|
+
captured_handle.set_propagated()
|
347
|
+
for captured_handle in self._captured_handles
|
348
|
+
]
|
349
|
+
)
|
350
|
+
|
351
|
+
def get_captured_ports(self) -> list[PortDeclaration]:
|
352
|
+
return [captured_handle.port for captured_handle in self._captured_handles]
|
353
|
+
|
354
|
+
def get_captured_args(
|
355
|
+
self, current_function: "FunctionClosure"
|
356
|
+
) -> list[HandleBinding]:
|
357
|
+
return [
|
358
|
+
(
|
359
|
+
captured_handle.handle
|
360
|
+
if _same_closure(current_function, captured_handle.defining_function)
|
361
|
+
else HandleBinding(name=captured_handle.mangled_name)
|
362
|
+
)
|
363
|
+
for captured_handle in self._captured_handles
|
364
|
+
]
|
365
|
+
|
366
|
+
def get_captured_mapping(self) -> SymbolParts:
|
367
|
+
return {
|
368
|
+
captured_handle.handle: [
|
369
|
+
SymbolPart(
|
370
|
+
source_handle=captured_handle.handle,
|
371
|
+
target_var_name=captured_handle.mangled_name,
|
372
|
+
target_var_type=captured_handle.quantum_type,
|
373
|
+
)
|
374
|
+
]
|
375
|
+
for captured_handle in self._captured_handles
|
376
|
+
if not captured_handle.is_propagated
|
377
|
+
}
|
378
|
+
|
379
|
+
def clone(self) -> "CapturedVars":
|
380
|
+
return CapturedVars(_captured_handles=list(self._captured_handles))
|
381
|
+
|
382
|
+
|
383
|
+
def _same_closure(closure_1: "FunctionClosure", closure_2: "FunctionClosure") -> bool:
|
384
|
+
return closure_1.depth == closure_2.depth
|
385
|
+
|
386
|
+
|
387
|
+
def validate_args_are_not_propagated(
|
388
|
+
args: Sequence[ArgValue], captured_vars: Sequence[HandleBinding]
|
389
|
+
) -> None:
|
390
|
+
if not captured_vars:
|
391
|
+
return
|
392
|
+
captured_handles = {demangle_handle(handle) for handle in captured_vars}
|
393
|
+
arg_handles = {
|
394
|
+
demangle_handle(arg) for arg in args if isinstance(arg, HandleBinding)
|
395
|
+
}
|
396
|
+
if any(
|
397
|
+
arg_handle.overlaps(captured_handle)
|
398
|
+
for arg_handle in arg_handles
|
399
|
+
for captured_handle in captured_handles
|
400
|
+
):
|
401
|
+
captured_handles_str = {str(handle) for handle in captured_handles}
|
402
|
+
arg_handles_str = {str(handle) for handle in arg_handles}
|
403
|
+
vars_msg = f"Explicitly passed variables: {arg_handles_str}, captured variables: {captured_handles_str}"
|
404
|
+
raise ClassiqExpansionError(
|
405
|
+
f"Cannot capture variables that are explicitly passed as arguments. "
|
406
|
+
f"{vars_msg}"
|
407
|
+
)
|
408
|
+
|
409
|
+
|
410
|
+
def validate_captured_directions(
|
411
|
+
captured_vars: CapturedVars, report_outin: bool = True
|
412
|
+
) -> None:
|
413
|
+
captured_inputs = [
|
414
|
+
captured_handle.handle.name
|
415
|
+
for captured_handle in captured_vars._captured_handles
|
416
|
+
if captured_handle.direction == PortDirection.Input
|
417
|
+
]
|
418
|
+
captured_outputs = [
|
419
|
+
captured_handle.handle.name
|
420
|
+
for captured_handle in captured_vars._captured_handles
|
421
|
+
if captured_handle.direction
|
422
|
+
in (
|
423
|
+
(PortDirection.Output, PortDirection.Outin)
|
424
|
+
if report_outin
|
425
|
+
else (PortDirection.Output,)
|
426
|
+
)
|
427
|
+
]
|
428
|
+
if len(captured_inputs) > 0:
|
429
|
+
raise ClassiqExpansionError(
|
430
|
+
f"Captured quantum variables {captured_inputs!r} cannot be used as inputs"
|
431
|
+
)
|
432
|
+
if len(captured_outputs) > 0:
|
433
|
+
raise ClassiqExpansionError(
|
434
|
+
f"Captured quantum variables {captured_outputs!r} cannot be used as outputs"
|
435
|
+
)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import re
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
from classiq.interface.generator.compiler_keywords import CAPTURE_SUFFIX
|
5
|
+
from classiq.interface.model.handle_binding import HANDLE_ID_SEPARATOR, HandleBinding
|
6
|
+
|
7
|
+
IDENTIFIER_PATTERN = r"[a-zA-Z_][a-zA-Z0-9_]*"
|
8
|
+
CAPTURE_PATTERN = re.compile(
|
9
|
+
rf"({IDENTIFIER_PATTERN}){CAPTURE_SUFFIX}{IDENTIFIER_PATTERN}__\d*"
|
10
|
+
)
|
11
|
+
ARRAY_CAST_SUFFIX = HANDLE_ID_SEPARATOR + "array_cast"
|
12
|
+
|
13
|
+
|
14
|
+
def mangle_captured_var_name(
|
15
|
+
var_name: str, function_name: str, function_depth: int
|
16
|
+
) -> str:
|
17
|
+
return f"{var_name}{CAPTURE_SUFFIX}{function_name}__{function_depth}"
|
18
|
+
|
19
|
+
|
20
|
+
def _match_capture_pattern(name: str) -> Optional[re.Match[str]]:
|
21
|
+
return re.match(CAPTURE_PATTERN, name)
|
22
|
+
|
23
|
+
|
24
|
+
def is_captured_var_name(name: str) -> bool:
|
25
|
+
return _match_capture_pattern(name) is not None
|
26
|
+
|
27
|
+
|
28
|
+
def demangle_capture_name(name: str) -> str:
|
29
|
+
match = _match_capture_pattern(name)
|
30
|
+
return match.group(1) if match else name
|
31
|
+
|
32
|
+
|
33
|
+
def demangle_handle(handle: HandleBinding) -> HandleBinding:
|
34
|
+
demangled_name = demangle_name(handle.name)
|
35
|
+
return handle.rename(demangled_name)
|
36
|
+
|
37
|
+
|
38
|
+
def demangle_name(name: str) -> str:
|
39
|
+
if HANDLE_ID_SEPARATOR not in name:
|
40
|
+
return name
|
41
|
+
if ARRAY_CAST_SUFFIX in name:
|
42
|
+
return name.split(ARRAY_CAST_SUFFIX)[0]
|
43
|
+
name = re.sub(r"([^_])_\d+$", r"\1", name)
|
44
|
+
name_parts = name.split(HANDLE_ID_SEPARATOR)
|
45
|
+
new_name_parts = [name_parts[0]]
|
46
|
+
for part in name_parts[1:]:
|
47
|
+
if re.fullmatch(r"\d+", part):
|
48
|
+
new_name_parts.append(f"[{part}]")
|
49
|
+
elif re.fullmatch(r"\d+_\d+", part):
|
50
|
+
part_left, part_right = part.split("_")
|
51
|
+
new_name_parts.append(f"[{part_left}:{part_right}]")
|
52
|
+
else:
|
53
|
+
new_name_parts.append(f".{part}")
|
54
|
+
new_name_parts = list(map(demangle_capture_name, new_name_parts))
|
55
|
+
new_name = "".join(new_name_parts)
|
56
|
+
return new_name
|
@@ -0,0 +1,171 @@
|
|
1
|
+
import dataclasses
|
2
|
+
import json
|
3
|
+
from collections.abc import Collection, Sequence
|
4
|
+
from dataclasses import dataclass, field
|
5
|
+
from functools import singledispatch
|
6
|
+
from typing import Any, Optional
|
7
|
+
|
8
|
+
from typing_extensions import Self
|
9
|
+
|
10
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
11
|
+
from classiq.interface.model.port_declaration import PortDeclaration
|
12
|
+
from classiq.interface.model.quantum_function_declaration import (
|
13
|
+
NamedParamsQuantumFunctionDeclaration,
|
14
|
+
PositionalArg,
|
15
|
+
)
|
16
|
+
from classiq.interface.model.quantum_lambda_function import QuantumCallable
|
17
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
18
|
+
|
19
|
+
from classiq.model_expansions.capturing.captured_vars import CapturedVars
|
20
|
+
from classiq.model_expansions.expression_renamer import ExpressionRenamer
|
21
|
+
from classiq.model_expansions.scope import (
|
22
|
+
Evaluated,
|
23
|
+
QuantumSymbol,
|
24
|
+
Scope,
|
25
|
+
evaluated_to_str as evaluated_classical_param_to_str,
|
26
|
+
)
|
27
|
+
from classiq.qmod.builtins.functions import permute
|
28
|
+
from classiq.qmod.quantum_function import GenerativeQFunc
|
29
|
+
|
30
|
+
|
31
|
+
@dataclass(frozen=True)
|
32
|
+
class Closure:
|
33
|
+
name: str
|
34
|
+
blocks: dict[str, Sequence[QuantumStatement]]
|
35
|
+
scope: Scope
|
36
|
+
positional_arg_declarations: Sequence[PositionalArg] = tuple()
|
37
|
+
captured_vars: CapturedVars = field(default_factory=CapturedVars)
|
38
|
+
|
39
|
+
@property
|
40
|
+
def port_declarations(self) -> dict[str, PortDeclaration]:
|
41
|
+
return {
|
42
|
+
param.name: param
|
43
|
+
for param in self.positional_arg_declarations
|
44
|
+
if isinstance(param, PortDeclaration)
|
45
|
+
}
|
46
|
+
|
47
|
+
|
48
|
+
@dataclass(frozen=True)
|
49
|
+
class GenerativeClosure(Closure):
|
50
|
+
generative_blocks: dict[str, GenerativeQFunc] = None # type:ignore[assignment]
|
51
|
+
|
52
|
+
|
53
|
+
@dataclass(frozen=True)
|
54
|
+
class FunctionClosure(Closure):
|
55
|
+
is_lambda: bool = False
|
56
|
+
is_atomic: bool = False
|
57
|
+
signature_scope: Scope = field(default_factory=Scope)
|
58
|
+
_depth: Optional[int] = None
|
59
|
+
|
60
|
+
@property
|
61
|
+
def depth(self) -> int:
|
62
|
+
if self._depth is None:
|
63
|
+
raise ClassiqInternalExpansionError
|
64
|
+
return self._depth
|
65
|
+
|
66
|
+
# creates a unique id for the function closure based on the arguments values.
|
67
|
+
# The closure is changing across the interpreter flow so it's closure_id may change
|
68
|
+
@property
|
69
|
+
def closure_id(self) -> str:
|
70
|
+
signature = _generate_closure_id(self.scope.data.values())
|
71
|
+
return f"{self.name}__{signature}"
|
72
|
+
|
73
|
+
@property
|
74
|
+
def body(self) -> Sequence[QuantumStatement]:
|
75
|
+
if self.name == permute.func_decl.name:
|
76
|
+
# permute is an old Qmod "generative" function that doesn't have a body
|
77
|
+
return []
|
78
|
+
return self.blocks["body"]
|
79
|
+
|
80
|
+
@classmethod
|
81
|
+
def create(
|
82
|
+
cls,
|
83
|
+
name: str,
|
84
|
+
scope: Scope,
|
85
|
+
body: Optional[Sequence[QuantumStatement]] = None,
|
86
|
+
positional_arg_declarations: Sequence[PositionalArg] = tuple(),
|
87
|
+
expr_renamer: Optional[ExpressionRenamer] = None,
|
88
|
+
is_lambda: bool = False,
|
89
|
+
is_atomic: bool = False,
|
90
|
+
**kwargs: Any,
|
91
|
+
) -> Self:
|
92
|
+
if expr_renamer:
|
93
|
+
positional_arg_declarations = (
|
94
|
+
expr_renamer.rename_positional_arg_declarations(
|
95
|
+
positional_arg_declarations
|
96
|
+
)
|
97
|
+
)
|
98
|
+
if body is not None:
|
99
|
+
body = expr_renamer.visit(body)
|
100
|
+
|
101
|
+
blocks = {"body": body} if body is not None else {}
|
102
|
+
return cls(
|
103
|
+
name,
|
104
|
+
blocks,
|
105
|
+
scope,
|
106
|
+
positional_arg_declarations,
|
107
|
+
CapturedVars(),
|
108
|
+
is_lambda,
|
109
|
+
is_atomic,
|
110
|
+
**kwargs,
|
111
|
+
)
|
112
|
+
|
113
|
+
def with_new_declaration(
|
114
|
+
self, declaration: NamedParamsQuantumFunctionDeclaration
|
115
|
+
) -> Self:
|
116
|
+
fields: dict = self.__dict__ | {
|
117
|
+
"name": declaration.name,
|
118
|
+
"positional_arg_declarations": declaration.positional_arg_declarations,
|
119
|
+
}
|
120
|
+
return type(self)(**fields)
|
121
|
+
|
122
|
+
def set_depth(self, depth: int) -> Self:
|
123
|
+
return dataclasses.replace(self, _depth=depth)
|
124
|
+
|
125
|
+
def clone(self) -> Self:
|
126
|
+
return dataclasses.replace(
|
127
|
+
self,
|
128
|
+
scope=self.scope.clone(),
|
129
|
+
signature_scope=self.signature_scope.clone(),
|
130
|
+
captured_vars=self.captured_vars.clone(),
|
131
|
+
)
|
132
|
+
|
133
|
+
def emit(self) -> QuantumCallable:
|
134
|
+
return self.name
|
135
|
+
|
136
|
+
|
137
|
+
@dataclass(frozen=True)
|
138
|
+
class GenerativeFunctionClosure(GenerativeClosure, FunctionClosure):
|
139
|
+
pass
|
140
|
+
|
141
|
+
|
142
|
+
def _generate_closure_id(evaluated_args: Collection[Evaluated]) -> str:
|
143
|
+
args_signature = [
|
144
|
+
_evaluated_arg_to_str(eval_arg.value) for eval_arg in evaluated_args
|
145
|
+
]
|
146
|
+
return json.dumps(args_signature)
|
147
|
+
|
148
|
+
|
149
|
+
@singledispatch
|
150
|
+
def _evaluated_arg_to_str(arg: Any) -> str:
|
151
|
+
if isinstance(arg, str):
|
152
|
+
return arg
|
153
|
+
if isinstance(arg, QuantumSymbol):
|
154
|
+
return _evaluated_quantum_symbol_to_str(arg)
|
155
|
+
if isinstance(arg, FunctionClosure):
|
156
|
+
return _evaluated_one_operand_to_str(arg)
|
157
|
+
if isinstance(arg, list) and arg and isinstance(arg[0], FunctionClosure):
|
158
|
+
return _evaluated_operands_list_to_str(arg)
|
159
|
+
return evaluated_classical_param_to_str(arg)
|
160
|
+
|
161
|
+
|
162
|
+
def _evaluated_quantum_symbol_to_str(port: QuantumSymbol) -> str:
|
163
|
+
return port.quantum_type.model_dump_json(exclude_none=True, exclude={"name"})
|
164
|
+
|
165
|
+
|
166
|
+
def _evaluated_one_operand_to_str(operand: FunctionClosure) -> str:
|
167
|
+
return operand.closure_id
|
168
|
+
|
169
|
+
|
170
|
+
def _evaluated_operands_list_to_str(arg: list[FunctionClosure]) -> str:
|
171
|
+
return json.dumps([_evaluated_one_operand_to_str(ope) for ope in arg])
|
File without changes
|