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,249 @@
|
|
1
|
+
from functools import singledispatchmethod
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from numpy.random import permutation
|
6
|
+
|
7
|
+
from classiq.interface.generator.expressions.expression import Expression
|
8
|
+
from classiq.interface.generator.functions.builtins.internal_operators import (
|
9
|
+
CONTROL_OPERATOR_NAME,
|
10
|
+
INVERT_OPERATOR_NAME,
|
11
|
+
WITHIN_APPLY_NAME,
|
12
|
+
)
|
13
|
+
from classiq.interface.model.allocate import Allocate
|
14
|
+
from classiq.interface.model.bind_operation import BindOperation
|
15
|
+
from classiq.interface.model.classical_if import ClassicalIf
|
16
|
+
from classiq.interface.model.control import Control
|
17
|
+
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
18
|
+
from classiq.interface.model.invert import Invert
|
19
|
+
from classiq.interface.model.model import Model
|
20
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
21
|
+
from classiq.interface.model.phase_operation import PhaseOperation
|
22
|
+
from classiq.interface.model.power import Power
|
23
|
+
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
24
|
+
QuantumAssignmentOperation,
|
25
|
+
)
|
26
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
27
|
+
from classiq.interface.model.quantum_function_declaration import (
|
28
|
+
NamedParamsQuantumFunctionDeclaration,
|
29
|
+
)
|
30
|
+
from classiq.interface.model.quantum_lambda_function import (
|
31
|
+
OperandIdentifier,
|
32
|
+
QuantumLambdaFunction,
|
33
|
+
)
|
34
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
35
|
+
from classiq.interface.model.repeat import Repeat
|
36
|
+
from classiq.interface.model.variable_declaration_statement import (
|
37
|
+
VariableDeclarationStatement,
|
38
|
+
)
|
39
|
+
from classiq.interface.model.within_apply_operation import WithinApply
|
40
|
+
|
41
|
+
from classiq.model_expansions.closure import (
|
42
|
+
Closure,
|
43
|
+
FunctionClosure,
|
44
|
+
GenerativeClosure,
|
45
|
+
GenerativeFunctionClosure,
|
46
|
+
)
|
47
|
+
from classiq.model_expansions.generative_functions import emit_generative_statements
|
48
|
+
from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
|
49
|
+
from classiq.model_expansions.quantum_operations import (
|
50
|
+
BindEmitter,
|
51
|
+
ClassicalIfEmitter,
|
52
|
+
QuantumFunctionCallEmitter,
|
53
|
+
RepeatEmitter,
|
54
|
+
VariableDeclarationStatementEmitter,
|
55
|
+
)
|
56
|
+
from classiq.model_expansions.quantum_operations.shallow_emitter import ShallowEmitter
|
57
|
+
from classiq.model_expansions.scope import Evaluated, Scope
|
58
|
+
from classiq.model_expansions.scope_initialization import (
|
59
|
+
add_functions_to_scope,
|
60
|
+
add_generative_functions_to_scope,
|
61
|
+
)
|
62
|
+
from classiq.qmod.builtins.functions import permute
|
63
|
+
from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
|
64
|
+
from classiq.qmod.quantum_function import GenerativeQFunc
|
65
|
+
|
66
|
+
|
67
|
+
class GenerativeInterpreter(BaseInterpreter):
|
68
|
+
def __init__(
|
69
|
+
self,
|
70
|
+
model: Model,
|
71
|
+
generative_functions: list[GenerativeQFunc],
|
72
|
+
) -> None:
|
73
|
+
super().__init__(model)
|
74
|
+
add_generative_functions_to_scope(generative_functions, self._top_level_scope)
|
75
|
+
|
76
|
+
def evaluate_lambda(self, function: QuantumLambdaFunction) -> Evaluated:
|
77
|
+
renamed_params = [
|
78
|
+
param.rename(function.pos_rename_params[idx])
|
79
|
+
for idx, param in enumerate(function.func_decl.positional_arg_declarations)
|
80
|
+
]
|
81
|
+
func_decl = NamedParamsQuantumFunctionDeclaration(
|
82
|
+
name=self._counted_name_allocator.allocate(
|
83
|
+
function.func_decl.name or "<lambda>"
|
84
|
+
),
|
85
|
+
positional_arg_declarations=renamed_params,
|
86
|
+
)
|
87
|
+
|
88
|
+
closure_class: type[FunctionClosure]
|
89
|
+
extra_args: dict[str, Any]
|
90
|
+
if function.is_generative():
|
91
|
+
closure_class = GenerativeFunctionClosure
|
92
|
+
extra_args = {
|
93
|
+
"generative_blocks": {
|
94
|
+
"body": GenerativeQFunc(function.py_callable, func_decl),
|
95
|
+
}
|
96
|
+
}
|
97
|
+
else:
|
98
|
+
closure_class = FunctionClosure
|
99
|
+
extra_args = {}
|
100
|
+
|
101
|
+
return Evaluated(
|
102
|
+
value=closure_class.create(
|
103
|
+
name=func_decl.name,
|
104
|
+
positional_arg_declarations=func_decl.positional_arg_declarations,
|
105
|
+
body=function.body,
|
106
|
+
scope=Scope(parent=self._builder.current_scope),
|
107
|
+
is_lambda=True,
|
108
|
+
**extra_args,
|
109
|
+
),
|
110
|
+
defining_function=self._builder.current_function,
|
111
|
+
)
|
112
|
+
|
113
|
+
@singledispatchmethod
|
114
|
+
def emit(self, statement: QuantumStatement) -> None: # type:ignore[override]
|
115
|
+
raise NotImplementedError(f"Cannot emit {statement!r}")
|
116
|
+
|
117
|
+
@emit.register
|
118
|
+
def _emit_quantum_function_call(self, call: QuantumFunctionCall) -> None:
|
119
|
+
self.emit_quantum_function_call(call)
|
120
|
+
|
121
|
+
def emit_quantum_function_call(self, call: QuantumFunctionCall) -> None:
|
122
|
+
QuantumFunctionCallEmitter(self).emit(call)
|
123
|
+
|
124
|
+
@emit.register
|
125
|
+
def emit_allocate(self, allocate: Allocate) -> None:
|
126
|
+
ShallowEmitter(self, "allocate", components=["size", "target"]).emit(allocate)
|
127
|
+
|
128
|
+
@emit.register
|
129
|
+
def emit_bind(self, bind: BindOperation) -> None:
|
130
|
+
BindEmitter(self).emit(bind)
|
131
|
+
|
132
|
+
@emit.register
|
133
|
+
def emit_quantum_assignment_operation(self, op: QuantumAssignmentOperation) -> None:
|
134
|
+
ShallowEmitter(
|
135
|
+
self, "assignment_operation", components=["expression", "result_var"]
|
136
|
+
).emit(op)
|
137
|
+
|
138
|
+
@emit.register
|
139
|
+
def emit_inplace_binary_operation(self, op: InplaceBinaryOperation) -> None:
|
140
|
+
ShallowEmitter(
|
141
|
+
self, "inplace_binary_operation", components=["target", "value"]
|
142
|
+
).emit(op)
|
143
|
+
|
144
|
+
@emit.register
|
145
|
+
def emit_variable_declaration(
|
146
|
+
self, variable_declaration: VariableDeclarationStatement
|
147
|
+
) -> None:
|
148
|
+
VariableDeclarationStatementEmitter(self).emit(variable_declaration)
|
149
|
+
|
150
|
+
@emit.register
|
151
|
+
def emit_classical_if(self, classical_if: ClassicalIf) -> None:
|
152
|
+
ClassicalIfEmitter(self).emit(classical_if)
|
153
|
+
|
154
|
+
@emit.register
|
155
|
+
def emit_within_apply(self, within_apply: WithinApply) -> None:
|
156
|
+
ShallowEmitter(
|
157
|
+
self,
|
158
|
+
WITHIN_APPLY_NAME,
|
159
|
+
components=["within", "apply", "compute", "action"],
|
160
|
+
).emit(within_apply)
|
161
|
+
|
162
|
+
@emit.register
|
163
|
+
def emit_invert(self, invert: Invert) -> None:
|
164
|
+
ShallowEmitter(self, INVERT_OPERATOR_NAME, components=["body"]).emit(invert)
|
165
|
+
|
166
|
+
@emit.register
|
167
|
+
def emit_repeat(self, repeat: Repeat) -> None:
|
168
|
+
RepeatEmitter(self).emit(repeat)
|
169
|
+
|
170
|
+
@emit.register
|
171
|
+
def emit_control(self, control: Control) -> None:
|
172
|
+
ShallowEmitter(
|
173
|
+
self,
|
174
|
+
CONTROL_OPERATOR_NAME,
|
175
|
+
components=["expression", "body", "else_block"],
|
176
|
+
).emit(control)
|
177
|
+
|
178
|
+
@emit.register
|
179
|
+
def emit_power(self, power: Power) -> None:
|
180
|
+
ShallowEmitter(self, CONTROL_OPERATOR_NAME, components=["power", "body"]).emit(
|
181
|
+
power
|
182
|
+
)
|
183
|
+
|
184
|
+
@emit.register
|
185
|
+
def emit_phase(self, phase: PhaseOperation) -> None:
|
186
|
+
ShallowEmitter(self, "phase", components=["expression", "theta"]).emit(phase)
|
187
|
+
|
188
|
+
def _expand_body(self, operation: Closure) -> None:
|
189
|
+
if isinstance(operation, FunctionClosure) and operation.name == "permute":
|
190
|
+
# special expansion since permute is generative
|
191
|
+
self._expand_permute()
|
192
|
+
elif isinstance(operation, GenerativeClosure):
|
193
|
+
args = [
|
194
|
+
self.evaluate(param.name)
|
195
|
+
for param in operation.positional_arg_declarations
|
196
|
+
]
|
197
|
+
emit_generative_statements(self, operation, args)
|
198
|
+
else:
|
199
|
+
super()._expand_body(operation)
|
200
|
+
|
201
|
+
def _expand_permute(self) -> None:
|
202
|
+
functions = self.evaluate("functions").as_type(list)
|
203
|
+
functions_permutation = permutation(np.array(range(len(functions))))
|
204
|
+
calls: list[QuantumFunctionCall] = []
|
205
|
+
for function_index in functions_permutation:
|
206
|
+
permute_call = QuantumFunctionCall(
|
207
|
+
function=OperandIdentifier(
|
208
|
+
name="functions", index=Expression(expr=f"{function_index}")
|
209
|
+
)
|
210
|
+
)
|
211
|
+
permute_call.set_func_decl(permute.func_decl)
|
212
|
+
calls.append(permute_call)
|
213
|
+
self._expand_block(calls, "body")
|
214
|
+
|
215
|
+
def update_generative_functions(
|
216
|
+
self, generative_functions: dict[str, GenerativeQFunc]
|
217
|
+
) -> None:
|
218
|
+
add_generative_functions_to_scope(
|
219
|
+
list(generative_functions.values()), self._top_level_scope
|
220
|
+
)
|
221
|
+
for name, gen_func in generative_functions.items():
|
222
|
+
if gen_func.compilation_metadata is not None:
|
223
|
+
self._functions_compilation_metadata[name] = (
|
224
|
+
gen_func.compilation_metadata
|
225
|
+
)
|
226
|
+
|
227
|
+
def update_declarative_functions(
|
228
|
+
self,
|
229
|
+
functions: dict[str, NativeFunctionDefinition],
|
230
|
+
qmodule: ModelStateContainer,
|
231
|
+
) -> None:
|
232
|
+
add_functions_to_scope(list(functions.values()), self._top_level_scope)
|
233
|
+
for dec_func_name in functions:
|
234
|
+
if dec_func_name in qmodule.functions_compilation_metadata:
|
235
|
+
self._functions_compilation_metadata[dec_func_name] = (
|
236
|
+
qmodule.functions_compilation_metadata[dec_func_name]
|
237
|
+
)
|
238
|
+
|
239
|
+
def add_purely_declarative_function(self, function: FunctionClosure) -> None:
|
240
|
+
functions_to_add = [function.name] + QMODULE.function_dependencies[
|
241
|
+
function.name
|
242
|
+
]
|
243
|
+
for func in functions_to_add:
|
244
|
+
if func not in self._expanded_functions and func in QMODULE.native_defs:
|
245
|
+
self._expanded_functions[func] = QMODULE.native_defs[func]
|
246
|
+
if func in QMODULE.functions_compilation_metadata:
|
247
|
+
self._expanded_functions_compilation_metadata[func] = (
|
248
|
+
QMODULE.functions_compilation_metadata[func]
|
249
|
+
)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
from classiq.interface.generator.expressions.handle_identifier import HandleIdentifier
|
4
|
+
from classiq.interface.generator.functions.classical_type import QmodPyObject
|
5
|
+
|
6
|
+
|
7
|
+
class HandleTable:
|
8
|
+
_handle_map: dict[HandleIdentifier, QmodPyObject] = {}
|
9
|
+
|
10
|
+
@classmethod
|
11
|
+
def get_handle_object(cls, hid: HandleIdentifier) -> Optional[QmodPyObject]:
|
12
|
+
return cls._handle_map.get(hid)
|
13
|
+
|
14
|
+
@classmethod
|
15
|
+
def set_handle_object(cls, qmod_object: QmodPyObject) -> HandleIdentifier:
|
16
|
+
hid = HandleIdentifier(id(qmod_object))
|
17
|
+
cls._handle_map[hid] = qmod_object
|
18
|
+
return hid
|
@@ -0,0 +1,9 @@
|
|
1
|
+
from classiq.model_expansions.quantum_operations.bind import BindEmitter
|
2
|
+
from classiq.model_expansions.quantum_operations.classicalif import ClassicalIfEmitter
|
3
|
+
from classiq.model_expansions.quantum_operations.quantum_function_call import (
|
4
|
+
QuantumFunctionCallEmitter,
|
5
|
+
)
|
6
|
+
from classiq.model_expansions.quantum_operations.repeat import RepeatEmitter
|
7
|
+
from classiq.model_expansions.quantum_operations.variable_decleration import (
|
8
|
+
VariableDeclarationStatementEmitter,
|
9
|
+
)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
from classiq.interface.exceptions import ClassiqExpansionError
|
2
|
+
from classiq.interface.model.bind_operation import BindOperation
|
3
|
+
|
4
|
+
from classiq.model_expansions.evaluators.parameter_types import (
|
5
|
+
evaluate_types_in_quantum_symbols,
|
6
|
+
)
|
7
|
+
from classiq.model_expansions.evaluators.quantum_type_utils import (
|
8
|
+
set_size,
|
9
|
+
validate_bind_targets,
|
10
|
+
)
|
11
|
+
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
12
|
+
from classiq.model_expansions.scope import QuantumSymbol
|
13
|
+
|
14
|
+
|
15
|
+
class BindEmitter(Emitter[BindOperation]):
|
16
|
+
def emit(self, bind: BindOperation, /) -> None:
|
17
|
+
inputs: list[QuantumSymbol] = [
|
18
|
+
self._interpreter.evaluate(arg).as_type(QuantumSymbol)
|
19
|
+
for arg in bind.in_handles
|
20
|
+
]
|
21
|
+
outputs: list[QuantumSymbol] = [
|
22
|
+
self._interpreter.evaluate(arg).as_type(QuantumSymbol)
|
23
|
+
for arg in bind.out_handles
|
24
|
+
]
|
25
|
+
inputs = evaluate_types_in_quantum_symbols(inputs, self._current_scope)
|
26
|
+
outputs = evaluate_types_in_quantum_symbols(outputs, self._current_scope)
|
27
|
+
validate_bind_targets(bind, self._current_scope)
|
28
|
+
unsized_outputs = [
|
29
|
+
output for output in outputs if not output.quantum_type.has_size_in_bits
|
30
|
+
]
|
31
|
+
|
32
|
+
if len(unsized_outputs) > 1:
|
33
|
+
raise ClassiqExpansionError(
|
34
|
+
f"Cannot perform the split operation {bind.in_handles[0].name} -> {{{', '.join(out_handle.name for out_handle in bind.out_handles)}}}:\n"
|
35
|
+
f"Quantum variables {', '.join(str(out_handle.handle) for out_handle in unsized_outputs)} are used as bind outputs, but their size cannot be inferred."
|
36
|
+
)
|
37
|
+
|
38
|
+
input_size = sum(input.quantum_type.size_in_bits for input in inputs)
|
39
|
+
output_size = sum(
|
40
|
+
output.quantum_type.size_in_bits
|
41
|
+
for output in outputs
|
42
|
+
if output.quantum_type.has_size_in_bits
|
43
|
+
)
|
44
|
+
|
45
|
+
if len(unsized_outputs) == 1:
|
46
|
+
set_size(
|
47
|
+
unsized_outputs[0].quantum_type,
|
48
|
+
input_size - output_size,
|
49
|
+
str(unsized_outputs[0].handle),
|
50
|
+
)
|
51
|
+
|
52
|
+
else:
|
53
|
+
if input_size != output_size:
|
54
|
+
raise ClassiqExpansionError(
|
55
|
+
f"The total size for the input and output of the bind operation must be the same. The in size is {input_size} and the out size is {output_size}"
|
56
|
+
)
|
57
|
+
|
58
|
+
self.emit_statement(
|
59
|
+
BindOperation(in_handles=bind.in_handles, out_handles=bind.out_handles)
|
60
|
+
)
|
@@ -0,0 +1,266 @@
|
|
1
|
+
from collections.abc import Sequence
|
2
|
+
from itertools import chain
|
3
|
+
from typing import (
|
4
|
+
TYPE_CHECKING,
|
5
|
+
Generic,
|
6
|
+
Optional,
|
7
|
+
cast,
|
8
|
+
)
|
9
|
+
|
10
|
+
from classiq.interface.debug_info.debug_info import FunctionDebugInfo
|
11
|
+
from classiq.interface.generator.generated_circuit_data import OperationLevel
|
12
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
13
|
+
ClassicalParameterDeclaration,
|
14
|
+
)
|
15
|
+
from classiq.interface.model.handle_binding import HandleBinding
|
16
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
17
|
+
from classiq.interface.model.port_declaration import PortDeclaration
|
18
|
+
from classiq.interface.model.quantum_function_call import ArgValue, QuantumFunctionCall
|
19
|
+
from classiq.interface.model.quantum_function_declaration import (
|
20
|
+
NamedParamsQuantumFunctionDeclaration,
|
21
|
+
PositionalArg,
|
22
|
+
)
|
23
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
24
|
+
from classiq.interface.model.variable_declaration_statement import (
|
25
|
+
VariableDeclarationStatement,
|
26
|
+
)
|
27
|
+
|
28
|
+
from classiq.model_expansions.capturing.captured_vars import (
|
29
|
+
validate_args_are_not_propagated,
|
30
|
+
)
|
31
|
+
from classiq.model_expansions.closure import FunctionClosure
|
32
|
+
from classiq.model_expansions.evaluators.argument_types import (
|
33
|
+
add_information_from_output_arguments,
|
34
|
+
)
|
35
|
+
from classiq.model_expansions.evaluators.parameter_types import (
|
36
|
+
evaluate_parameter_types_from_args,
|
37
|
+
)
|
38
|
+
from classiq.model_expansions.function_builder import (
|
39
|
+
FunctionContext,
|
40
|
+
)
|
41
|
+
from classiq.model_expansions.quantum_operations.emitter import (
|
42
|
+
Emitter,
|
43
|
+
QuantumStatementT,
|
44
|
+
)
|
45
|
+
from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
|
46
|
+
from classiq.model_expansions.transformers.var_splitter import VarSplitter
|
47
|
+
from classiq.qmod.builtins.functions import allocate, free
|
48
|
+
|
49
|
+
if TYPE_CHECKING:
|
50
|
+
from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
|
51
|
+
|
52
|
+
|
53
|
+
class CallEmitter(Generic[QuantumStatementT], Emitter[QuantumStatementT], VarSplitter):
|
54
|
+
def __init__(self, interpreter: "BaseInterpreter") -> None:
|
55
|
+
Emitter.__init__(self, interpreter)
|
56
|
+
VarSplitter.__init__(self, interpreter._builder.current_scope)
|
57
|
+
|
58
|
+
@staticmethod
|
59
|
+
def _should_wrap(body: Sequence[QuantumStatement]) -> bool:
|
60
|
+
# This protects shadowing of captured variables (i.e, bad user code) by wrapping the body in a function
|
61
|
+
# I'm sure there are better ways to handle it, but this is the simplest way to do it for now
|
62
|
+
return any(isinstance(stmt, VariableDeclarationStatement) for stmt in body)
|
63
|
+
|
64
|
+
def _create_expanded_wrapping_function(
|
65
|
+
self, name: str, body: Sequence[QuantumStatement]
|
66
|
+
) -> QuantumFunctionCall:
|
67
|
+
wrapping_function = FunctionClosure.create(
|
68
|
+
name=self._counted_name_allocator.allocate(name),
|
69
|
+
body=body,
|
70
|
+
scope=Scope(parent=self._current_scope),
|
71
|
+
is_lambda=True,
|
72
|
+
)
|
73
|
+
return self._create_quantum_function_call(wrapping_function, list())
|
74
|
+
|
75
|
+
def _emit_quantum_function_call(
|
76
|
+
self,
|
77
|
+
function: FunctionClosure,
|
78
|
+
args: list[ArgValue],
|
79
|
+
propagated_debug_info: Optional[FunctionDebugInfo] = None,
|
80
|
+
) -> QuantumFunctionCall:
|
81
|
+
call = self._create_quantum_function_call(
|
82
|
+
function, args, propagated_debug_info=propagated_debug_info
|
83
|
+
)
|
84
|
+
self.emit_statement(call)
|
85
|
+
return call
|
86
|
+
|
87
|
+
def _create_quantum_function_call(
|
88
|
+
self,
|
89
|
+
function: FunctionClosure,
|
90
|
+
args: list[ArgValue],
|
91
|
+
propagated_debug_info: Optional[FunctionDebugInfo] = None,
|
92
|
+
) -> QuantumFunctionCall:
|
93
|
+
function = function.clone()
|
94
|
+
function = function.set_depth(self._builder.current_function.depth + 1)
|
95
|
+
evaluated_args = [self._interpreter.evaluate(arg) for arg in args]
|
96
|
+
new_declaration = self._prepare_fully_typed_declaration(
|
97
|
+
function, evaluated_args
|
98
|
+
)
|
99
|
+
new_positional_arg_decls = new_declaration.positional_arg_declarations
|
100
|
+
if not self.should_expand_function(function, evaluated_args):
|
101
|
+
is_atomic = True
|
102
|
+
new_declaration = self._expanded_functions_by_name.get(
|
103
|
+
function.name, new_declaration
|
104
|
+
)
|
105
|
+
else:
|
106
|
+
is_atomic = False
|
107
|
+
new_declaration = self._expand_function(
|
108
|
+
evaluated_args, new_declaration, function
|
109
|
+
)
|
110
|
+
|
111
|
+
new_positional_args = self._get_new_positional_args(
|
112
|
+
evaluated_args, is_atomic, new_positional_arg_decls
|
113
|
+
)
|
114
|
+
captured_args = function.captured_vars.get_captured_args(
|
115
|
+
self._builder.current_function
|
116
|
+
)
|
117
|
+
validate_args_are_not_propagated(new_positional_args, captured_args)
|
118
|
+
new_positional_args.extend(captured_args)
|
119
|
+
new_call = QuantumFunctionCall(
|
120
|
+
function=new_declaration.name, positional_args=new_positional_args
|
121
|
+
)
|
122
|
+
is_allocate_or_free = (
|
123
|
+
new_call.func_name == allocate.func_decl.name
|
124
|
+
or new_call.func_name == free.func_decl.name
|
125
|
+
)
|
126
|
+
parameters = {
|
127
|
+
arg_decl.name: FunctionDebugInfo.param_controller(value=evaluated_arg.value)
|
128
|
+
for arg_decl, evaluated_arg in zip(new_positional_arg_decls, evaluated_args)
|
129
|
+
if isinstance(arg_decl, ClassicalParameterDeclaration)
|
130
|
+
}
|
131
|
+
|
132
|
+
port_to_passed_variable_map = {
|
133
|
+
arg_decl.name: str(evaluated_arg.value.handle)
|
134
|
+
for arg_decl, evaluated_arg in zip(new_positional_arg_decls, evaluated_args)
|
135
|
+
if isinstance(arg_decl, PortDeclaration)
|
136
|
+
}
|
137
|
+
self._debug_info[new_call.uuid] = FunctionDebugInfo(
|
138
|
+
name=new_call.func_name,
|
139
|
+
level=OperationLevel.QMOD_FUNCTION_CALL,
|
140
|
+
parameters=(
|
141
|
+
parameters
|
142
|
+
if propagated_debug_info is None
|
143
|
+
else propagated_debug_info.parameters
|
144
|
+
),
|
145
|
+
is_allocate_or_free=is_allocate_or_free,
|
146
|
+
port_to_passed_variable_map=port_to_passed_variable_map,
|
147
|
+
)
|
148
|
+
new_call.set_func_decl(new_declaration)
|
149
|
+
return new_call
|
150
|
+
|
151
|
+
def should_expand_function(
|
152
|
+
self, function: FunctionClosure, args: list[Evaluated]
|
153
|
+
) -> bool:
|
154
|
+
return not function.is_atomic
|
155
|
+
|
156
|
+
def _expand_function(
|
157
|
+
self,
|
158
|
+
args: list[Evaluated],
|
159
|
+
decl: NamedParamsQuantumFunctionDeclaration,
|
160
|
+
function: FunctionClosure,
|
161
|
+
) -> NamedParamsQuantumFunctionDeclaration:
|
162
|
+
self._add_params_to_scope(decl.positional_arg_declarations, args, function)
|
163
|
+
context = self._expand_operation(function.with_new_declaration(decl))
|
164
|
+
function_context = cast(FunctionContext, context)
|
165
|
+
closure_id = function_context.closure.closure_id
|
166
|
+
if closure_id in self._expanded_functions:
|
167
|
+
function_def = self._expanded_functions[closure_id]
|
168
|
+
self._expanded_functions_compilation_metadata[
|
169
|
+
function_def.name
|
170
|
+
].occurrences_number += 1
|
171
|
+
return function_def
|
172
|
+
|
173
|
+
function_def = self._create_function_definition(function_context)
|
174
|
+
self._expanded_functions[closure_id] = function_def
|
175
|
+
self._top_level_scope[function_def.name] = Evaluated(
|
176
|
+
value=function_context.closure.with_new_declaration(function_def)
|
177
|
+
)
|
178
|
+
compilation_metadata = self._functions_compilation_metadata.get(function.name)
|
179
|
+
if compilation_metadata is not None:
|
180
|
+
self._expanded_functions_compilation_metadata[function_def.name] = (
|
181
|
+
compilation_metadata
|
182
|
+
)
|
183
|
+
return function_def
|
184
|
+
|
185
|
+
def _create_function_definition(
|
186
|
+
self, function_context: FunctionContext
|
187
|
+
) -> NativeFunctionDefinition:
|
188
|
+
func_def = self._builder.create_definition(function_context)
|
189
|
+
|
190
|
+
captured_ports = function_context.closure.captured_vars.get_captured_ports()
|
191
|
+
if len(captured_ports) == 0:
|
192
|
+
return func_def
|
193
|
+
func_def.positional_arg_declarations = list(
|
194
|
+
chain.from_iterable((func_def.positional_arg_declarations, captured_ports))
|
195
|
+
)
|
196
|
+
|
197
|
+
if not function_context.is_lambda:
|
198
|
+
return func_def
|
199
|
+
func_def.body = self.rewrite(
|
200
|
+
func_def.body, function_context.closure.captured_vars.get_captured_mapping()
|
201
|
+
)
|
202
|
+
|
203
|
+
return func_def
|
204
|
+
|
205
|
+
@staticmethod
|
206
|
+
def _add_params_to_scope(
|
207
|
+
parameters: Sequence[PositionalArg],
|
208
|
+
arguments: Sequence[Evaluated],
|
209
|
+
closure: FunctionClosure,
|
210
|
+
) -> None:
|
211
|
+
for parameter, argument in zip(parameters, arguments):
|
212
|
+
if isinstance(argument.value, QuantumSymbol):
|
213
|
+
assert isinstance(parameter, PortDeclaration)
|
214
|
+
closure.scope[parameter.name] = Evaluated(
|
215
|
+
QuantumSymbol(
|
216
|
+
handle=HandleBinding(name=parameter.name),
|
217
|
+
quantum_type=parameter.quantum_type,
|
218
|
+
),
|
219
|
+
defining_function=closure,
|
220
|
+
)
|
221
|
+
else:
|
222
|
+
closure.scope[parameter.name] = argument
|
223
|
+
|
224
|
+
def _get_new_positional_args(
|
225
|
+
self,
|
226
|
+
evaluated_args: list[Evaluated],
|
227
|
+
is_atomic: bool,
|
228
|
+
new_positional_arg_decls: Sequence[PositionalArg],
|
229
|
+
) -> list[ArgValue]:
|
230
|
+
evaluated_args = add_information_from_output_arguments(
|
231
|
+
new_positional_arg_decls, evaluated_args
|
232
|
+
)
|
233
|
+
if is_atomic:
|
234
|
+
return [arg.emit() for arg in evaluated_args]
|
235
|
+
|
236
|
+
positional_args = [
|
237
|
+
arg.emit() for arg in evaluated_args if isinstance(arg.value, QuantumSymbol)
|
238
|
+
]
|
239
|
+
|
240
|
+
return positional_args
|
241
|
+
|
242
|
+
def _prepare_fully_typed_declaration(
|
243
|
+
self, function: FunctionClosure, evaluated_args: list[Evaluated]
|
244
|
+
) -> NamedParamsQuantumFunctionDeclaration:
|
245
|
+
"""
|
246
|
+
Given, for example,
|
247
|
+
def my_func(x: int, q: QArray["x"], p: QArray[]) -> None:
|
248
|
+
...
|
249
|
+
def main(...):
|
250
|
+
...
|
251
|
+
allocate(5, s)
|
252
|
+
my_func(3, r, s)
|
253
|
+
The code below will evaluate x to be 3, q to be of size 3 and p to be of size 5.
|
254
|
+
Note that it requires a scope for the parameter declaration space, which is
|
255
|
+
different from the call scope. For example, the former uses r,s and the latter
|
256
|
+
uses p, q.
|
257
|
+
"""
|
258
|
+
# The signature scope is passed as a separate argument to avoid contaminating the statement execution scope
|
259
|
+
return NamedParamsQuantumFunctionDeclaration(
|
260
|
+
name=function.name,
|
261
|
+
positional_arg_declarations=evaluate_parameter_types_from_args(
|
262
|
+
function,
|
263
|
+
function.signature_scope,
|
264
|
+
evaluated_args,
|
265
|
+
),
|
266
|
+
)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
from collections.abc import Sequence
|
2
|
+
|
3
|
+
from classiq.interface.model.classical_if import ClassicalIf
|
4
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
5
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
6
|
+
|
7
|
+
from classiq.model_expansions.closure import FunctionClosure
|
8
|
+
from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
|
9
|
+
from classiq.model_expansions.scope import Scope
|
10
|
+
|
11
|
+
|
12
|
+
def _is_all_identity_calls(body: Sequence[QuantumStatement]) -> bool:
|
13
|
+
return all(
|
14
|
+
isinstance(stmt, QuantumFunctionCall) and stmt.func_name.lower() == "identity"
|
15
|
+
for stmt in body
|
16
|
+
)
|
17
|
+
|
18
|
+
|
19
|
+
class ClassicalIfEmitter(CallEmitter[ClassicalIf]):
|
20
|
+
def emit(self, classical_if: ClassicalIf, /) -> None:
|
21
|
+
condition = self._interpreter.evaluate(classical_if.condition).as_type(bool)
|
22
|
+
op_name = "then" if condition else "else"
|
23
|
+
is_generative = classical_if.is_generative()
|
24
|
+
|
25
|
+
body: Sequence[QuantumStatement]
|
26
|
+
if is_generative:
|
27
|
+
if not classical_if.has_generative_block(op_name):
|
28
|
+
return
|
29
|
+
context = self._expand_generative_context(classical_if, op_name, op_name)
|
30
|
+
context.blocks["body"] = context.blocks[op_name]
|
31
|
+
context.blocks.pop(op_name)
|
32
|
+
body = context.statements("body")
|
33
|
+
else:
|
34
|
+
body = classical_if.then if condition else classical_if.else_
|
35
|
+
|
36
|
+
if _is_all_identity_calls(body):
|
37
|
+
return
|
38
|
+
|
39
|
+
if is_generative or not self._should_wrap(body):
|
40
|
+
for stmt in body:
|
41
|
+
if is_generative:
|
42
|
+
self._interpreter._builder.emit_statement(stmt)
|
43
|
+
else:
|
44
|
+
self._interpreter.emit_statement(stmt)
|
45
|
+
return
|
46
|
+
|
47
|
+
then_else_func = FunctionClosure.create(
|
48
|
+
name=self._counted_name_allocator.allocate("then" if condition else "else"),
|
49
|
+
body=body,
|
50
|
+
scope=Scope(parent=self._current_scope),
|
51
|
+
is_lambda=True,
|
52
|
+
)
|
53
|
+
self._emit_quantum_function_call(then_else_func, list())
|