classiq 0.38.0__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 +47 -32
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
- classiq/_internals/api_wrapper.py +235 -97
- classiq/_internals/async_utils.py +1 -3
- classiq/_internals/authentication/auth0.py +26 -10
- classiq/_internals/authentication/authentication.py +11 -0
- classiq/_internals/authentication/device.py +10 -5
- classiq/_internals/authentication/password_manager.py +18 -6
- classiq/_internals/authentication/token_manager.py +10 -5
- classiq/_internals/client.py +94 -33
- classiq/_internals/config.py +3 -4
- classiq/_internals/host_checker.py +38 -15
- classiq/_internals/jobs.py +60 -57
- classiq/_internals/type_validation.py +9 -9
- classiq/analyzer/__init__.py +1 -3
- classiq/analyzer/analyzer.py +24 -19
- classiq/analyzer/analyzer_utilities.py +10 -10
- classiq/analyzer/rb.py +15 -15
- classiq/analyzer/show_interactive_hack.py +27 -4
- 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 +165 -158
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +4 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +51 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +12 -12
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +8 -6
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +7 -11
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +67 -40
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
- classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +2 -2
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +15 -20
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +14 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +11 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +1 -2
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +2 -3
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +5 -8
- classiq/applications/combinatorial_optimization/__init__.py +20 -6
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
- classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +35 -33
- 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 +48 -42
- classiq/applications/grover/__init__.py +9 -0
- classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +52 -51
- classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
- classiq/applications/libraries/qmci_library.py +22 -0
- classiq/applications/qnn/__init__.py +2 -4
- classiq/applications/qnn/circuit_utils.py +6 -6
- 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 +1 -1
- 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 +5 -5
- classiq/applications/qsvm/__init__.py +6 -4
- classiq/applications/qsvm/qsvm.py +3 -6
- classiq/applications/qsvm/qsvm_data_generation.py +3 -3
- 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 +20 -115
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +43 -13
- classiq/interface/analyzer/cytoscape_graph.py +15 -9
- classiq/interface/analyzer/result.py +28 -32
- classiq/interface/applications/qsvm.py +20 -29
- classiq/interface/ast_node.py +16 -0
- classiq/interface/backend/backend_preferences.py +390 -121
- classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
- classiq/interface/backend/pydantic_backend.py +25 -22
- classiq/interface/backend/quantum_backend_providers.py +69 -16
- classiq/interface/chemistry/fermionic_operator.py +30 -21
- classiq/interface/chemistry/ground_state_problem.py +28 -25
- classiq/interface/chemistry/molecule.py +14 -10
- classiq/interface/chemistry/operator.py +64 -231
- classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
- classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
- classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
- classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
- classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +8 -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/debug_info.py +86 -0
- classiq/{exceptions.py → interface/exceptions.py} +37 -9
- 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/execution_preferences.py +26 -114
- classiq/interface/executor/execution_request.py +24 -46
- classiq/interface/executor/execution_result.py +30 -8
- classiq/interface/executor/iqae_result.py +4 -6
- classiq/interface/executor/optimizer_preferences.py +17 -14
- classiq/interface/executor/quantum_code.py +28 -24
- classiq/interface/executor/quantum_instruction_set.py +2 -2
- classiq/interface/executor/register_initialization.py +11 -14
- classiq/interface/executor/result.py +83 -56
- classiq/interface/executor/vqe_result.py +10 -10
- classiq/interface/finance/function_input.py +35 -25
- classiq/interface/finance/gaussian_model_input.py +5 -5
- classiq/interface/finance/log_normal_model_input.py +4 -4
- classiq/interface/finance/model_input.py +4 -4
- classiq/interface/generator/adjacency.py +1 -3
- classiq/interface/generator/amplitude_loading.py +22 -12
- classiq/interface/generator/ansatz_library.py +5 -5
- classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
- 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 +46 -5
- classiq/interface/generator/arith/arithmetic.py +35 -16
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +6 -7
- classiq/interface/generator/arith/arithmetic_expression_abc.py +66 -25
- classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -11
- classiq/interface/generator/arith/arithmetic_expression_validator.py +47 -43
- classiq/interface/generator/arith/arithmetic_operations.py +14 -6
- 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 +3 -2
- classiq/interface/generator/arith/binary_ops.py +218 -130
- classiq/interface/generator/arith/endianness.py +1 -1
- classiq/interface/generator/arith/extremum_operations.py +96 -25
- classiq/interface/generator/arith/logical_ops.py +14 -12
- classiq/interface/generator/arith/number_utils.py +12 -6
- classiq/interface/generator/arith/register_user_input.py +60 -37
- classiq/interface/generator/arith/unary_ops.py +49 -29
- 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 +3 -3
- 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 +7 -7
- classiq/interface/generator/compiler_keywords.py +5 -1
- classiq/interface/generator/complex_type.py +13 -18
- classiq/interface/generator/constant.py +3 -4
- classiq/interface/generator/control_state.py +34 -29
- 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 +21 -5
- 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 +5 -5
- classiq/interface/generator/expressions/expression.py +26 -14
- 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 +34 -8
- 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 +19 -11
- classiq/interface/generator/finance.py +2 -2
- 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 +36 -64
- classiq/interface/generator/functions/__init__.py +0 -22
- 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 +153 -20
- classiq/interface/generator/grover_diffuser.py +32 -25
- classiq/interface/generator/grover_operator.py +34 -25
- 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 +9 -9
- classiq/interface/generator/hardware/hardware_data.py +72 -34
- classiq/interface/generator/hardware_efficient_ansatz.py +20 -16
- classiq/interface/generator/hartree_fock.py +13 -5
- classiq/interface/generator/identity.py +10 -6
- classiq/interface/generator/linear_pauli_rotations.py +32 -20
- classiq/interface/generator/mcmt_method.py +1 -1
- classiq/interface/generator/mcu.py +17 -15
- classiq/interface/generator/mcx.py +24 -17
- classiq/interface/generator/model/__init__.py +2 -5
- classiq/interface/generator/model/constraints.py +26 -8
- classiq/interface/generator/model/model.py +27 -190
- classiq/interface/generator/model/preferences/preferences.py +115 -41
- classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +14 -17
- classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
- classiq/interface/generator/oracles/custom_oracle.py +15 -13
- classiq/interface/generator/oracles/oracle_abc.py +7 -7
- 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 +41 -30
- classiq/interface/generator/qsvm.py +9 -10
- classiq/interface/generator/quantum_function_call.py +88 -73
- classiq/interface/generator/quantum_program.py +41 -24
- classiq/interface/generator/range_types.py +11 -12
- classiq/interface/generator/register_role.py +18 -6
- classiq/interface/generator/slice_parsing_utils.py +5 -5
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +30 -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 +4 -7
- classiq/interface/generator/state_preparation/state_preparation.py +25 -20
- 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 +7 -11
- classiq/interface/generator/ucc.py +5 -4
- classiq/interface/generator/unitary_gate.py +5 -5
- classiq/interface/generator/user_defined_function_params.py +4 -1
- classiq/interface/generator/validations/flow_graph.py +7 -7
- classiq/interface/generator/validations/validator_functions.py +4 -4
- classiq/interface/generator/visitor.py +23 -16
- classiq/interface/hardware.py +29 -8
- classiq/interface/helpers/classproperty.py +8 -0
- classiq/interface/helpers/custom_encoders.py +2 -2
- 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 -5
- classiq/interface/helpers/validation_helpers.py +3 -20
- classiq/interface/helpers/versioned_model.py +1 -4
- 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 +29 -69
- classiq/interface/model/allocate.py +16 -0
- classiq/interface/model/bind_operation.py +32 -9
- 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 +29 -24
- classiq/interface/model/invert.py +12 -0
- classiq/interface/model/model.py +69 -61
- classiq/interface/model/native_function_definition.py +17 -20
- 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 +30 -18
- 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 +141 -343
- classiq/interface/model/quantum_function_declaration.py +190 -157
- classiq/interface/model/quantum_lambda_function.py +33 -32
- classiq/interface/model/quantum_statement.py +71 -12
- classiq/interface/model/quantum_type.py +177 -40
- classiq/interface/model/quantum_variable_declaration.py +3 -25
- classiq/interface/model/repeat.py +15 -0
- classiq/interface/model/statement_block.py +40 -14
- classiq/interface/model/validation_handle.py +13 -6
- classiq/interface/model/variable_declaration_statement.py +3 -1
- classiq/interface/model/within_apply_operation.py +7 -5
- classiq/interface/server/global_versions.py +6 -7
- classiq/interface/server/routes.py +17 -21
- classiq/interface/source_reference.py +59 -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 +10 -10
- classiq/qmod/builtins/__init__.py +19 -2
- classiq/qmod/builtins/classical_execution_primitives.py +36 -14
- classiq/qmod/builtins/classical_functions.py +39 -43
- 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 +373 -40
- classiq/qmod/builtins/structs.py +103 -80
- classiq/qmod/cfunc.py +2 -2
- classiq/qmod/classical_function.py +4 -8
- classiq/qmod/cparam.py +64 -0
- classiq/qmod/create_model_function.py +56 -0
- classiq/qmod/declaration_inferrer.py +143 -101
- classiq/qmod/expression_query.py +20 -4
- classiq/qmod/generative.py +42 -0
- classiq/qmod/model_state_container.py +18 -6
- classiq/qmod/native/__init__.py +7 -0
- classiq/qmod/native/expression_to_qmod.py +16 -11
- classiq/qmod/native/pretty_printer.py +187 -97
- 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 +60 -8
- classiq/qmod/qmod_constant.py +93 -26
- classiq/qmod/qmod_parameter.py +68 -59
- classiq/qmod/qmod_variable.py +468 -155
- classiq/qmod/quantum_callable.py +17 -7
- classiq/qmod/quantum_expandable.py +269 -96
- classiq/qmod/quantum_function.py +196 -41
- 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 +147 -123
- classiq/qmod/symbolic_expr.py +27 -12
- classiq/qmod/symbolic_type.py +2 -5
- classiq/qmod/type_attribute_remover.py +32 -0
- classiq/qmod/utilities.py +98 -4
- classiq/qmod/write_qmod.py +17 -3
- classiq/synthesis.py +210 -22
- {classiq-0.38.0.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -9
- classiq-0.65.3.dist-info/RECORD +521 -0
- classiq/_internals/_qfunc_ext.py +0 -6
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -25
- classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -65
- classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +0 -243
- classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
- 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/interface/executor/aws_execution_cost.py +0 -73
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
- classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
- 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/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 -1229
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
- classiq/interface/generator/functions/foreign_function_definition.py +0 -114
- classiq/interface/generator/functions/function_implementation.py +0 -107
- classiq/interface/generator/functions/native_function_definition.py +0 -155
- classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
- classiq/interface/generator/functions/register.py +0 -44
- classiq/interface/generator/functions/register_mapping_data.py +0 -106
- 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 -74
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
- classiq/interface/ide/show.py +0 -34
- classiq/interface/model/call_synthesis_data.py +0 -68
- classiq/interface/model/common_model_types.py +0 -23
- classiq/interface/model/quantum_expressions/control_state.py +0 -38
- classiq/interface/model/quantum_if_operation.py +0 -94
- 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 -156
- 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 -462
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -229
- classiq/qmod/builtins/functions.py +0 -913
- classiq/qmod/qmod_struct.py +0 -37
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -205
- 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.38.0.dist-info/RECORD +0 -454
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
- /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
- /classiq/{interface/generator/credit_risk_example → applications/hamiltonian}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
- /classiq/interface/{model/resolvers → debug_info}/__init__.py +0 -0
- /classiq/{_internals → interface}/enum_utils.py +0 -0
- /classiq/interface/{model/validations → generator/functions/builtins}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → model_expansions/__init__.py} +0 -0
- {classiq-0.38.0.dist-info → classiq-0.65.3.dist-info}/WHEEL +0 -0
@@ -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())
|
@@ -0,0 +1,87 @@
|
|
1
|
+
from itertools import chain
|
2
|
+
from typing import TYPE_CHECKING, Generic
|
3
|
+
|
4
|
+
from classiq.interface.generator.functions.port_declaration import (
|
5
|
+
PortDeclarationDirection,
|
6
|
+
)
|
7
|
+
from classiq.interface.model.port_declaration import PortDeclaration
|
8
|
+
|
9
|
+
from classiq.model_expansions.closure import FunctionClosure, GenerativeClosure
|
10
|
+
from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
|
11
|
+
from classiq.model_expansions.quantum_operations.emitter import QuantumStatementT
|
12
|
+
from classiq.model_expansions.scope import Evaluated
|
13
|
+
from classiq.qmod.model_state_container import QMODULE
|
14
|
+
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
from classiq.model_expansions.interpreters.generative_interpreter import (
|
17
|
+
GenerativeInterpreter,
|
18
|
+
)
|
19
|
+
|
20
|
+
|
21
|
+
class DeclarativeCallEmitter(
|
22
|
+
Generic[QuantumStatementT], CallEmitter[QuantumStatementT]
|
23
|
+
):
|
24
|
+
_interpreter: "GenerativeInterpreter"
|
25
|
+
|
26
|
+
def __init__(self, interpreter: "GenerativeInterpreter") -> None:
|
27
|
+
super().__init__(interpreter)
|
28
|
+
|
29
|
+
def should_expand_function(
|
30
|
+
self, function: FunctionClosure, args: list[Evaluated]
|
31
|
+
) -> bool:
|
32
|
+
if not super().should_expand_function(function, args):
|
33
|
+
return False
|
34
|
+
|
35
|
+
if self._is_function_purely_declarative(
|
36
|
+
function
|
37
|
+
) and self._are_args_purely_declarative(args):
|
38
|
+
self._interpreter.add_purely_declarative_function(function)
|
39
|
+
return False
|
40
|
+
|
41
|
+
return True
|
42
|
+
|
43
|
+
def _is_function_purely_declarative(self, function: FunctionClosure) -> bool:
|
44
|
+
if function.name not in QMODULE.native_defs:
|
45
|
+
return False
|
46
|
+
|
47
|
+
if isinstance(function, GenerativeClosure):
|
48
|
+
return False
|
49
|
+
|
50
|
+
if any(
|
51
|
+
not param.quantum_type.is_instantiated
|
52
|
+
for param in function.positional_arg_declarations
|
53
|
+
if isinstance(param, PortDeclaration)
|
54
|
+
and param.direction == PortDeclarationDirection.Output
|
55
|
+
):
|
56
|
+
return False
|
57
|
+
|
58
|
+
dependencies = QMODULE.function_dependencies[function.name]
|
59
|
+
return self._are_identifiers_purely_declarative(dependencies)
|
60
|
+
|
61
|
+
def _are_args_purely_declarative(self, args: list[Evaluated]) -> bool:
|
62
|
+
values = [arg.value for arg in args]
|
63
|
+
function_inputs: list[FunctionClosure] = list(
|
64
|
+
chain.from_iterable(
|
65
|
+
(
|
66
|
+
[arg]
|
67
|
+
if isinstance(arg, FunctionClosure)
|
68
|
+
else (
|
69
|
+
arg
|
70
|
+
if isinstance(arg, list)
|
71
|
+
and any(isinstance(item, FunctionClosure) for item in arg)
|
72
|
+
else []
|
73
|
+
)
|
74
|
+
)
|
75
|
+
for arg in values
|
76
|
+
)
|
77
|
+
)
|
78
|
+
if any(func.is_lambda for func in function_inputs):
|
79
|
+
return False
|
80
|
+
dependencies = [func.name for func in function_inputs if not func.is_lambda]
|
81
|
+
return self._are_identifiers_purely_declarative(dependencies)
|
82
|
+
|
83
|
+
def _are_identifiers_purely_declarative(self, dependencies: list[str]) -> bool:
|
84
|
+
return not any(
|
85
|
+
isinstance(self._current_scope[dep].value, GenerativeClosure)
|
86
|
+
for dep in dependencies
|
87
|
+
)
|
@@ -0,0 +1,181 @@
|
|
1
|
+
import ast
|
2
|
+
from abc import abstractmethod
|
3
|
+
from typing import (
|
4
|
+
TYPE_CHECKING,
|
5
|
+
Generic,
|
6
|
+
Optional,
|
7
|
+
TypeVar,
|
8
|
+
Union,
|
9
|
+
)
|
10
|
+
|
11
|
+
import sympy
|
12
|
+
|
13
|
+
from classiq.interface.debug_info.debug_info import DebugInfoCollection
|
14
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
15
|
+
from classiq.interface.generator.expressions.evaluated_expression import (
|
16
|
+
EvaluatedExpression,
|
17
|
+
)
|
18
|
+
from classiq.interface.generator.expressions.expression import Expression
|
19
|
+
from classiq.interface.generator.functions.port_declaration import (
|
20
|
+
PortDeclarationDirection,
|
21
|
+
)
|
22
|
+
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
23
|
+
from classiq.interface.model.handle_binding import HandleBinding
|
24
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
25
|
+
from classiq.interface.model.quantum_function_declaration import (
|
26
|
+
NamedParamsQuantumFunctionDeclaration,
|
27
|
+
)
|
28
|
+
from classiq.interface.model.quantum_statement import QuantumOperation, QuantumStatement
|
29
|
+
|
30
|
+
from classiq.model_expansions.closure import Closure, GenerativeClosure
|
31
|
+
from classiq.model_expansions.function_builder import (
|
32
|
+
OperationBuilder,
|
33
|
+
OperationContext,
|
34
|
+
)
|
35
|
+
from classiq.model_expansions.scope import QuantumSymbol, Scope
|
36
|
+
from classiq.model_expansions.sympy_conversion.sympy_to_python import (
|
37
|
+
translate_sympy_quantum_expression,
|
38
|
+
)
|
39
|
+
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
40
|
+
from classiq.model_expansions.visitors.variable_references import VarRefCollector
|
41
|
+
from classiq.qmod.quantum_function import GenerativeQFunc
|
42
|
+
|
43
|
+
if TYPE_CHECKING:
|
44
|
+
from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
|
45
|
+
|
46
|
+
QuantumStatementT = TypeVar("QuantumStatementT", bound=QuantumStatement)
|
47
|
+
|
48
|
+
|
49
|
+
class Emitter(Generic[QuantumStatementT]):
|
50
|
+
def __init__(self, interpreter: "BaseInterpreter") -> None:
|
51
|
+
self._interpreter = interpreter
|
52
|
+
|
53
|
+
self._machine_precision = self._interpreter._model.preferences.machine_precision
|
54
|
+
self._expanded_functions_compilation_metadata = (
|
55
|
+
self._interpreter._expanded_functions_compilation_metadata
|
56
|
+
)
|
57
|
+
self._functions_compilation_metadata = (
|
58
|
+
self._interpreter._functions_compilation_metadata
|
59
|
+
)
|
60
|
+
|
61
|
+
@abstractmethod
|
62
|
+
def emit(self, statement: QuantumStatementT, /) -> None:
|
63
|
+
pass
|
64
|
+
|
65
|
+
def _expand_operation(self, closure: Closure) -> OperationContext:
|
66
|
+
return self._interpreter._expand_operation(closure)
|
67
|
+
|
68
|
+
@property
|
69
|
+
def _builder(self) -> OperationBuilder:
|
70
|
+
return self._interpreter._builder
|
71
|
+
|
72
|
+
@property
|
73
|
+
def _current_scope(self) -> Scope:
|
74
|
+
return self._builder.current_scope
|
75
|
+
|
76
|
+
@property
|
77
|
+
def _top_level_scope(self) -> Scope:
|
78
|
+
return self._interpreter._top_level_scope
|
79
|
+
|
80
|
+
@property
|
81
|
+
def _expanded_functions(self) -> dict[str, NativeFunctionDefinition]:
|
82
|
+
return self._interpreter._expanded_functions
|
83
|
+
|
84
|
+
@property
|
85
|
+
def _expanded_functions_by_name(self) -> dict[str, NativeFunctionDefinition]:
|
86
|
+
return nameables_to_dict(list(self._interpreter._expanded_functions.values()))
|
87
|
+
|
88
|
+
@property
|
89
|
+
def _counted_name_allocator(self) -> CountedNameAllocator:
|
90
|
+
return self._interpreter._counted_name_allocator
|
91
|
+
|
92
|
+
@property
|
93
|
+
def _debug_info(self) -> DebugInfoCollection:
|
94
|
+
return self._interpreter._model.debug_info
|
95
|
+
|
96
|
+
def _expand_generative_context(
|
97
|
+
self,
|
98
|
+
op: QuantumOperation,
|
99
|
+
context_name: str,
|
100
|
+
block_names: Union[None, str, list[str]] = None,
|
101
|
+
func_decl: Optional[NamedParamsQuantumFunctionDeclaration] = None,
|
102
|
+
) -> OperationContext:
|
103
|
+
if isinstance(block_names, str):
|
104
|
+
block_names = [block_names]
|
105
|
+
block_names = block_names or ["body"]
|
106
|
+
func_decl = func_decl or NamedParamsQuantumFunctionDeclaration(
|
107
|
+
name=context_name
|
108
|
+
)
|
109
|
+
gen_closure = GenerativeClosure(
|
110
|
+
name=func_decl.name,
|
111
|
+
scope=Scope(parent=self._interpreter._builder.current_scope),
|
112
|
+
blocks={},
|
113
|
+
generative_blocks={
|
114
|
+
block_name: GenerativeQFunc(
|
115
|
+
op.get_generative_block(block_name), func_decl
|
116
|
+
)
|
117
|
+
for block_name in block_names
|
118
|
+
},
|
119
|
+
)
|
120
|
+
context = self._interpreter._expand_operation(gen_closure)
|
121
|
+
op.clear_generative_blocks()
|
122
|
+
return context
|
123
|
+
|
124
|
+
def _evaluate_expression(
|
125
|
+
self, expression: Expression, preserve_bool_ops: bool = False
|
126
|
+
) -> Expression:
|
127
|
+
evaluated_expression = self._interpreter.evaluate(expression)
|
128
|
+
if isinstance(evaluated_expression.value, sympy.Basic):
|
129
|
+
new_expression = Expression(
|
130
|
+
expr=translate_sympy_quantum_expression(
|
131
|
+
evaluated_expression.value,
|
132
|
+
preserve_bool_ops=preserve_bool_ops,
|
133
|
+
)
|
134
|
+
)
|
135
|
+
else:
|
136
|
+
new_expression = Expression(expr=str(evaluated_expression.value))
|
137
|
+
new_expression._evaluated_expr = EvaluatedExpression(
|
138
|
+
value=evaluated_expression.value
|
139
|
+
)
|
140
|
+
return new_expression
|
141
|
+
|
142
|
+
def emit_statement(self, statement: QuantumStatement) -> None:
|
143
|
+
if isinstance(statement, QuantumOperation):
|
144
|
+
self._update_captured_vars(statement)
|
145
|
+
self._builder.emit_statement(statement)
|
146
|
+
|
147
|
+
def _update_captured_vars(self, op: QuantumOperation) -> None:
|
148
|
+
handles = (
|
149
|
+
[(handle, PortDeclarationDirection.Input) for handle in op.inputs]
|
150
|
+
+ [(handle, PortDeclarationDirection.Output) for handle in op.outputs]
|
151
|
+
+ [(handle, PortDeclarationDirection.Inout) for handle in op.inouts]
|
152
|
+
)
|
153
|
+
for handle, direction in handles:
|
154
|
+
self._capture_handle(handle, direction)
|
155
|
+
|
156
|
+
def _capture_handle(
|
157
|
+
self, handle: HandleBinding, direction: PortDeclarationDirection
|
158
|
+
) -> None:
|
159
|
+
if handle.name not in self._current_scope:
|
160
|
+
return
|
161
|
+
defining_function = self._current_scope[handle.name].defining_function
|
162
|
+
if defining_function is None:
|
163
|
+
raise ClassiqInternalExpansionError
|
164
|
+
symbol: QuantumSymbol = self._interpreter.evaluate(handle).value
|
165
|
+
self._builder.current_block.captured_vars.capture_handle(
|
166
|
+
handle=symbol.handle,
|
167
|
+
quantum_type=symbol.quantum_type,
|
168
|
+
defining_function=defining_function,
|
169
|
+
direction=direction,
|
170
|
+
)
|
171
|
+
|
172
|
+
def capture_handles_in_expression(self, expr: Expression) -> None:
|
173
|
+
vrc = VarRefCollector(ignore_duplicated_handles=True)
|
174
|
+
vrc.visit(ast.parse(expr.expr))
|
175
|
+
handles = dict.fromkeys(
|
176
|
+
handle
|
177
|
+
for handle in vrc.var_handles
|
178
|
+
if isinstance(self._current_scope[handle.name].value, QuantumSymbol)
|
179
|
+
)
|
180
|
+
for handle in handles:
|
181
|
+
self._capture_handle(handle, PortDeclarationDirection.Inout)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
4
|
+
|
5
|
+
from classiq.model_expansions.closure import FunctionClosure
|
6
|
+
from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
|
7
|
+
from classiq.model_expansions.quantum_operations.declarative_call_emitter import (
|
8
|
+
DeclarativeCallEmitter,
|
9
|
+
)
|
10
|
+
from classiq.qmod.semantics.error_manager import ErrorManager
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
from classiq.model_expansions.interpreters.base_interpreter import BaseInterpreter
|
14
|
+
|
15
|
+
|
16
|
+
class QuantumFunctionCallEmitter(CallEmitter[QuantumFunctionCall]):
|
17
|
+
def __init__(self, interpreter: "BaseInterpreter") -> None:
|
18
|
+
super().__init__(interpreter)
|
19
|
+
self._model = self._interpreter._model
|
20
|
+
|
21
|
+
def emit(self, call: QuantumFunctionCall, /) -> None:
|
22
|
+
function = self._interpreter.evaluate(call.function).as_type(FunctionClosure)
|
23
|
+
args = call.positional_args
|
24
|
+
with ErrorManager().call(function.name):
|
25
|
+
self._emit_quantum_function_call(
|
26
|
+
function, args, self._debug_info.get(call.uuid)
|
27
|
+
)
|
28
|
+
|
29
|
+
|
30
|
+
class DeclarativeQuantumFunctionCallEmitter(
|
31
|
+
QuantumFunctionCallEmitter, DeclarativeCallEmitter
|
32
|
+
):
|
33
|
+
pass
|
@@ -0,0 +1,56 @@
|
|
1
|
+
from classiq.interface.exceptions import ClassiqExpansionError
|
2
|
+
from classiq.interface.generator.expressions.expression import Expression
|
3
|
+
from classiq.interface.generator.functions.builtins.internal_operators import (
|
4
|
+
REPEAT_OPERATOR_NAME,
|
5
|
+
)
|
6
|
+
from classiq.interface.generator.functions.classical_type import Integer
|
7
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
8
|
+
ClassicalParameterDeclaration,
|
9
|
+
)
|
10
|
+
from classiq.interface.model.repeat import Repeat
|
11
|
+
|
12
|
+
from classiq.model_expansions.closure import FunctionClosure, GenerativeFunctionClosure
|
13
|
+
from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
|
14
|
+
from classiq.model_expansions.scope import Scope
|
15
|
+
from classiq.qmod.quantum_function import GenerativeQFunc
|
16
|
+
|
17
|
+
|
18
|
+
class RepeatEmitter(CallEmitter[Repeat]):
|
19
|
+
def emit(self, repeat: Repeat, /) -> None:
|
20
|
+
count = self._interpreter.evaluate(repeat.count).as_type(int)
|
21
|
+
if count < 0:
|
22
|
+
raise ClassiqExpansionError(
|
23
|
+
f"repeat count must be non-negative, got {count}"
|
24
|
+
)
|
25
|
+
op_name = self._counted_name_allocator.allocate(REPEAT_OPERATOR_NAME)
|
26
|
+
for i in range(count):
|
27
|
+
self._emit_iteration(repeat, i, op_name)
|
28
|
+
|
29
|
+
def _emit_iteration(self, repeat: Repeat, i: int, op_name: str) -> None:
|
30
|
+
closure_constructor: type[FunctionClosure]
|
31
|
+
extra_args: dict
|
32
|
+
if repeat.is_generative():
|
33
|
+
closure_constructor = GenerativeFunctionClosure
|
34
|
+
extra_args = {
|
35
|
+
"generative_blocks": {
|
36
|
+
"body": GenerativeQFunc(
|
37
|
+
repeat.get_generative_block("body"),
|
38
|
+
),
|
39
|
+
}
|
40
|
+
}
|
41
|
+
else:
|
42
|
+
closure_constructor = FunctionClosure
|
43
|
+
extra_args = {}
|
44
|
+
iteration_function = closure_constructor.create(
|
45
|
+
name=op_name,
|
46
|
+
positional_arg_declarations=[
|
47
|
+
ClassicalParameterDeclaration(
|
48
|
+
name=repeat.iter_var, classical_type=Integer()
|
49
|
+
)
|
50
|
+
],
|
51
|
+
body=repeat.body,
|
52
|
+
scope=Scope(parent=self._current_scope),
|
53
|
+
is_lambda=True,
|
54
|
+
**extra_args,
|
55
|
+
)
|
56
|
+
self._emit_quantum_function_call(iteration_function, [Expression(expr=str(i))])
|