classiq 0.38.0__py3-none-any.whl → 0.65.4__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.4.dist-info}/METADATA +16 -9
- classiq-0.65.4.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.4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
import re
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
from classiq.interface.generator.compiler_keywords import CAPTURE_SUFFIX
|
5
|
+
from classiq.interface.model.handle_binding import HANDLE_ID_SEPARATOR, HandleBinding
|
6
|
+
|
7
|
+
IDENTIFIER_PATTERN = r"[a-zA-Z_][a-zA-Z0-9_]*"
|
8
|
+
CAPTURE_PATTERN = re.compile(
|
9
|
+
rf"({IDENTIFIER_PATTERN}){CAPTURE_SUFFIX}{IDENTIFIER_PATTERN}__\d*"
|
10
|
+
)
|
11
|
+
ARRAY_CAST_SUFFIX = HANDLE_ID_SEPARATOR + "array_cast"
|
12
|
+
|
13
|
+
|
14
|
+
def mangle_captured_var_name(
|
15
|
+
var_name: str, function_name: str, function_depth: int
|
16
|
+
) -> str:
|
17
|
+
return f"{var_name}{CAPTURE_SUFFIX}{function_name}__{function_depth}"
|
18
|
+
|
19
|
+
|
20
|
+
def _match_capture_pattern(name: str) -> Optional[re.Match[str]]:
|
21
|
+
return re.match(CAPTURE_PATTERN, name)
|
22
|
+
|
23
|
+
|
24
|
+
def is_captured_var_name(name: str) -> bool:
|
25
|
+
return _match_capture_pattern(name) is not None
|
26
|
+
|
27
|
+
|
28
|
+
def demangle_capture_name(name: str) -> str:
|
29
|
+
match = _match_capture_pattern(name)
|
30
|
+
return match.group(1) if match else name
|
31
|
+
|
32
|
+
|
33
|
+
def demangle_handle(handle: HandleBinding) -> HandleBinding:
|
34
|
+
demangled_name = demangle_name(handle.name)
|
35
|
+
return handle.rename(demangled_name)
|
36
|
+
|
37
|
+
|
38
|
+
def demangle_name(name: str) -> str:
|
39
|
+
if HANDLE_ID_SEPARATOR not in name:
|
40
|
+
return name
|
41
|
+
if ARRAY_CAST_SUFFIX in name:
|
42
|
+
return name.split(ARRAY_CAST_SUFFIX)[0]
|
43
|
+
name = re.sub(r"([^_])_\d+$", r"\1", name)
|
44
|
+
name_parts = name.split(HANDLE_ID_SEPARATOR)
|
45
|
+
new_name_parts = [name_parts[0]]
|
46
|
+
for part in name_parts[1:]:
|
47
|
+
if re.fullmatch(r"\d+", part):
|
48
|
+
new_name_parts.append(f"[{part}]")
|
49
|
+
elif re.fullmatch(r"\d+_\d+", part):
|
50
|
+
part_left, part_right = part.split("_")
|
51
|
+
new_name_parts.append(f"[{part_left}:{part_right}]")
|
52
|
+
else:
|
53
|
+
new_name_parts.append(f".{part}")
|
54
|
+
new_name_parts = list(map(demangle_capture_name, new_name_parts))
|
55
|
+
new_name = "".join(new_name_parts)
|
56
|
+
return new_name
|
@@ -0,0 +1,171 @@
|
|
1
|
+
import dataclasses
|
2
|
+
import json
|
3
|
+
from collections.abc import Collection, Sequence
|
4
|
+
from dataclasses import dataclass, field
|
5
|
+
from functools import singledispatch
|
6
|
+
from typing import Any, Optional
|
7
|
+
|
8
|
+
from typing_extensions import Self
|
9
|
+
|
10
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
11
|
+
from classiq.interface.model.port_declaration import PortDeclaration
|
12
|
+
from classiq.interface.model.quantum_function_declaration import (
|
13
|
+
NamedParamsQuantumFunctionDeclaration,
|
14
|
+
PositionalArg,
|
15
|
+
)
|
16
|
+
from classiq.interface.model.quantum_lambda_function import QuantumCallable
|
17
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
18
|
+
|
19
|
+
from classiq.model_expansions.capturing.captured_vars import CapturedVars
|
20
|
+
from classiq.model_expansions.expression_renamer import ExpressionRenamer
|
21
|
+
from classiq.model_expansions.scope import (
|
22
|
+
Evaluated,
|
23
|
+
QuantumSymbol,
|
24
|
+
Scope,
|
25
|
+
evaluated_to_str as evaluated_classical_param_to_str,
|
26
|
+
)
|
27
|
+
from classiq.qmod.builtins.functions import permute
|
28
|
+
from classiq.qmod.quantum_function import GenerativeQFunc
|
29
|
+
|
30
|
+
|
31
|
+
@dataclass(frozen=True)
|
32
|
+
class Closure:
|
33
|
+
name: str
|
34
|
+
blocks: dict[str, Sequence[QuantumStatement]]
|
35
|
+
scope: Scope
|
36
|
+
positional_arg_declarations: Sequence[PositionalArg] = tuple()
|
37
|
+
captured_vars: CapturedVars = field(default_factory=CapturedVars)
|
38
|
+
|
39
|
+
@property
|
40
|
+
def port_declarations(self) -> dict[str, PortDeclaration]:
|
41
|
+
return {
|
42
|
+
param.name: param
|
43
|
+
for param in self.positional_arg_declarations
|
44
|
+
if isinstance(param, PortDeclaration)
|
45
|
+
}
|
46
|
+
|
47
|
+
|
48
|
+
@dataclass(frozen=True)
|
49
|
+
class GenerativeClosure(Closure):
|
50
|
+
generative_blocks: dict[str, GenerativeQFunc] = None # type:ignore[assignment]
|
51
|
+
|
52
|
+
|
53
|
+
@dataclass(frozen=True)
|
54
|
+
class FunctionClosure(Closure):
|
55
|
+
is_lambda: bool = False
|
56
|
+
is_atomic: bool = False
|
57
|
+
signature_scope: Scope = field(default_factory=Scope)
|
58
|
+
_depth: Optional[int] = None
|
59
|
+
|
60
|
+
@property
|
61
|
+
def depth(self) -> int:
|
62
|
+
if self._depth is None:
|
63
|
+
raise ClassiqInternalExpansionError
|
64
|
+
return self._depth
|
65
|
+
|
66
|
+
# creates a unique id for the function closure based on the arguments values.
|
67
|
+
# The closure is changing across the interpreter flow so it's closure_id may change
|
68
|
+
@property
|
69
|
+
def closure_id(self) -> str:
|
70
|
+
signature = _generate_closure_id(self.scope.data.values())
|
71
|
+
return f"{self.name}__{signature}"
|
72
|
+
|
73
|
+
@property
|
74
|
+
def body(self) -> Sequence[QuantumStatement]:
|
75
|
+
if self.name == permute.func_decl.name:
|
76
|
+
# permute is an old Qmod "generative" function that doesn't have a body
|
77
|
+
return []
|
78
|
+
return self.blocks["body"]
|
79
|
+
|
80
|
+
@classmethod
|
81
|
+
def create(
|
82
|
+
cls,
|
83
|
+
name: str,
|
84
|
+
scope: Scope,
|
85
|
+
body: Optional[Sequence[QuantumStatement]] = None,
|
86
|
+
positional_arg_declarations: Sequence[PositionalArg] = tuple(),
|
87
|
+
expr_renamer: Optional[ExpressionRenamer] = None,
|
88
|
+
is_lambda: bool = False,
|
89
|
+
is_atomic: bool = False,
|
90
|
+
**kwargs: Any,
|
91
|
+
) -> Self:
|
92
|
+
if expr_renamer:
|
93
|
+
positional_arg_declarations = (
|
94
|
+
expr_renamer.rename_positional_arg_declarations(
|
95
|
+
positional_arg_declarations
|
96
|
+
)
|
97
|
+
)
|
98
|
+
if body is not None:
|
99
|
+
body = expr_renamer.visit(body)
|
100
|
+
|
101
|
+
blocks = {"body": body} if body is not None else {}
|
102
|
+
return cls(
|
103
|
+
name,
|
104
|
+
blocks,
|
105
|
+
scope,
|
106
|
+
positional_arg_declarations,
|
107
|
+
CapturedVars(),
|
108
|
+
is_lambda,
|
109
|
+
is_atomic,
|
110
|
+
**kwargs,
|
111
|
+
)
|
112
|
+
|
113
|
+
def with_new_declaration(
|
114
|
+
self, declaration: NamedParamsQuantumFunctionDeclaration
|
115
|
+
) -> Self:
|
116
|
+
fields: dict = self.__dict__ | {
|
117
|
+
"name": declaration.name,
|
118
|
+
"positional_arg_declarations": declaration.positional_arg_declarations,
|
119
|
+
}
|
120
|
+
return type(self)(**fields)
|
121
|
+
|
122
|
+
def set_depth(self, depth: int) -> Self:
|
123
|
+
return dataclasses.replace(self, _depth=depth)
|
124
|
+
|
125
|
+
def clone(self) -> Self:
|
126
|
+
return dataclasses.replace(
|
127
|
+
self,
|
128
|
+
scope=self.scope.clone(),
|
129
|
+
signature_scope=self.signature_scope.clone(),
|
130
|
+
captured_vars=self.captured_vars.clone(),
|
131
|
+
)
|
132
|
+
|
133
|
+
def emit(self) -> QuantumCallable:
|
134
|
+
return self.name
|
135
|
+
|
136
|
+
|
137
|
+
@dataclass(frozen=True)
|
138
|
+
class GenerativeFunctionClosure(GenerativeClosure, FunctionClosure):
|
139
|
+
pass
|
140
|
+
|
141
|
+
|
142
|
+
def _generate_closure_id(evaluated_args: Collection[Evaluated]) -> str:
|
143
|
+
args_signature = [
|
144
|
+
_evaluated_arg_to_str(eval_arg.value) for eval_arg in evaluated_args
|
145
|
+
]
|
146
|
+
return json.dumps(args_signature)
|
147
|
+
|
148
|
+
|
149
|
+
@singledispatch
|
150
|
+
def _evaluated_arg_to_str(arg: Any) -> str:
|
151
|
+
if isinstance(arg, str):
|
152
|
+
return arg
|
153
|
+
if isinstance(arg, QuantumSymbol):
|
154
|
+
return _evaluated_quantum_symbol_to_str(arg)
|
155
|
+
if isinstance(arg, FunctionClosure):
|
156
|
+
return _evaluated_one_operand_to_str(arg)
|
157
|
+
if isinstance(arg, list) and arg and isinstance(arg[0], FunctionClosure):
|
158
|
+
return _evaluated_operands_list_to_str(arg)
|
159
|
+
return evaluated_classical_param_to_str(arg)
|
160
|
+
|
161
|
+
|
162
|
+
def _evaluated_quantum_symbol_to_str(port: QuantumSymbol) -> str:
|
163
|
+
return port.quantum_type.model_dump_json(exclude_none=True, exclude={"name"})
|
164
|
+
|
165
|
+
|
166
|
+
def _evaluated_one_operand_to_str(operand: FunctionClosure) -> str:
|
167
|
+
return operand.closure_id
|
168
|
+
|
169
|
+
|
170
|
+
def _evaluated_operands_list_to_str(arg: list[FunctionClosure]) -> str:
|
171
|
+
return json.dumps([_evaluated_one_operand_to_str(ope) for ope in arg])
|
File without changes
|
@@ -0,0 +1,158 @@
|
|
1
|
+
from collections.abc import Sequence
|
2
|
+
from enum import Enum
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
from classiq.interface.exceptions import ClassiqExpansionError
|
6
|
+
from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
|
7
|
+
from classiq.interface.generator.expressions.qmod_struct_instance import (
|
8
|
+
QmodStructInstance,
|
9
|
+
)
|
10
|
+
from classiq.interface.generator.functions.classical_type import (
|
11
|
+
StructMetaType,
|
12
|
+
)
|
13
|
+
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
14
|
+
from classiq.interface.generator.functions.type_name import (
|
15
|
+
TypeName,
|
16
|
+
)
|
17
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
18
|
+
AnonClassicalParameterDeclaration,
|
19
|
+
)
|
20
|
+
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
21
|
+
from classiq.interface.model.quantum_function_declaration import (
|
22
|
+
AnonPositionalArg,
|
23
|
+
AnonQuantumOperandDeclaration,
|
24
|
+
)
|
25
|
+
|
26
|
+
from classiq.model_expansions.closure import FunctionClosure
|
27
|
+
from classiq.model_expansions.evaluators.type_type_match import check_signature_match
|
28
|
+
from classiq.model_expansions.scope import Evaluated, QuantumSymbol
|
29
|
+
from classiq.qmod.model_state_container import QMODULE
|
30
|
+
from classiq.qmod.qmod_parameter import CInt, get_qmod_type
|
31
|
+
|
32
|
+
|
33
|
+
def check_type_match(
|
34
|
+
parameters: Sequence[AnonPositionalArg],
|
35
|
+
arguments: list[Evaluated],
|
36
|
+
function_name: str,
|
37
|
+
) -> None:
|
38
|
+
if len(parameters) != len(arguments):
|
39
|
+
raise ClassiqExpansionError(
|
40
|
+
f"Function {function_name!r} takes {len(parameters)} arguments but "
|
41
|
+
f"{len(arguments)} were given"
|
42
|
+
)
|
43
|
+
for parameter, evaluated_arg in zip(parameters, arguments):
|
44
|
+
check_arg_type_match(evaluated_arg.value, parameter, function_name)
|
45
|
+
|
46
|
+
|
47
|
+
def check_arg_type_match(
|
48
|
+
argument: Any, parameter: AnonPositionalArg, function_name: str
|
49
|
+
) -> None:
|
50
|
+
message_prefix = (
|
51
|
+
f"Argument {str(argument)!r} to parameter {parameter.name!r} of function "
|
52
|
+
f"{function_name!r} has incompatible type; "
|
53
|
+
)
|
54
|
+
if isinstance(parameter, AnonPortDeclaration):
|
55
|
+
error_message = message_prefix + "expected quantum variable"
|
56
|
+
_check_qvar_type_match(argument, error_message)
|
57
|
+
elif isinstance(parameter, AnonQuantumOperandDeclaration):
|
58
|
+
if parameter.is_list:
|
59
|
+
error_message = message_prefix + "expected list of operands"
|
60
|
+
_check_operand_list_type_match(
|
61
|
+
argument, parameter, function_name, error_message
|
62
|
+
)
|
63
|
+
else:
|
64
|
+
error_message = message_prefix + "expected operand"
|
65
|
+
_check_operand_type_match(argument, parameter, function_name, error_message)
|
66
|
+
elif isinstance(parameter, AnonClassicalParameterDeclaration):
|
67
|
+
error_message = (
|
68
|
+
message_prefix + f"expected {_resolve_type_name(parameter.classical_type)}"
|
69
|
+
)
|
70
|
+
_check_classical_type_match(argument, parameter, error_message)
|
71
|
+
else:
|
72
|
+
raise ClassiqExpansionError(
|
73
|
+
f"unexpected parameter declaration type: {type(parameter).__name__}"
|
74
|
+
)
|
75
|
+
|
76
|
+
|
77
|
+
def _check_qvar_type_match(argument: Any, error_message: str) -> None:
|
78
|
+
if not isinstance(argument, QuantumSymbol):
|
79
|
+
raise ClassiqExpansionError(error_message)
|
80
|
+
|
81
|
+
|
82
|
+
def _check_operand_list_type_match(
|
83
|
+
argument: Any,
|
84
|
+
parameter: AnonQuantumOperandDeclaration,
|
85
|
+
function_name: str,
|
86
|
+
error_message: str,
|
87
|
+
) -> None:
|
88
|
+
if not isinstance(argument, list) or any(
|
89
|
+
not isinstance(op, FunctionClosure) for op in argument
|
90
|
+
):
|
91
|
+
raise ClassiqExpansionError(error_message)
|
92
|
+
for idx, operand in enumerate(argument):
|
93
|
+
if operand.positional_arg_declarations is not None:
|
94
|
+
check_signature_match(
|
95
|
+
parameter.positional_arg_declarations,
|
96
|
+
operand.positional_arg_declarations,
|
97
|
+
f"operand #{idx + 1} in parameter {parameter.name!r} "
|
98
|
+
f"in function {function_name!r}",
|
99
|
+
)
|
100
|
+
|
101
|
+
|
102
|
+
def _check_operand_type_match(
|
103
|
+
argument: Any,
|
104
|
+
parameter: AnonQuantumOperandDeclaration,
|
105
|
+
function_name: str,
|
106
|
+
error_message: str,
|
107
|
+
) -> None:
|
108
|
+
if not isinstance(argument, FunctionClosure):
|
109
|
+
raise ClassiqExpansionError(error_message)
|
110
|
+
if argument.positional_arg_declarations is not None:
|
111
|
+
check_signature_match(
|
112
|
+
parameter.positional_arg_declarations,
|
113
|
+
argument.positional_arg_declarations,
|
114
|
+
f"operand {parameter.name!r} in function {function_name!r}",
|
115
|
+
)
|
116
|
+
|
117
|
+
|
118
|
+
def _check_classical_type_match(
|
119
|
+
argument: Any, parameter: AnonClassicalParameterDeclaration, error_message: str
|
120
|
+
) -> None:
|
121
|
+
classical_type = parameter.classical_type
|
122
|
+
type_name = _resolve_type_name(classical_type)
|
123
|
+
type_is_struct = (
|
124
|
+
isinstance(classical_type, TypeName)
|
125
|
+
and classical_type.name in QMODULE.type_decls
|
126
|
+
)
|
127
|
+
type_is_enum = (
|
128
|
+
isinstance(classical_type, TypeName)
|
129
|
+
and classical_type.name in QMODULE.enum_decls
|
130
|
+
)
|
131
|
+
arg_is_qvar = isinstance(argument, QmodSizedProxy)
|
132
|
+
arg_is_builtin = argument.__class__.__module__ == "builtins"
|
133
|
+
arg_is_enum = isinstance(argument, Enum)
|
134
|
+
arg_is_struct = isinstance(argument, QmodStructInstance)
|
135
|
+
arg_struct_name = None if not arg_is_struct else argument.struct_declaration.name
|
136
|
+
if (
|
137
|
+
arg_is_qvar
|
138
|
+
or (arg_is_builtin and (type_is_struct or type_is_enum))
|
139
|
+
or (arg_is_struct and (not type_is_struct or arg_struct_name != type_name))
|
140
|
+
or (
|
141
|
+
arg_is_enum
|
142
|
+
and get_qmod_type(classical_type) != CInt
|
143
|
+
and (not type_is_enum or type(argument).__name__ != type_name)
|
144
|
+
)
|
145
|
+
):
|
146
|
+
raise ClassiqExpansionError(error_message)
|
147
|
+
|
148
|
+
|
149
|
+
def _resolve_type_name(classical_type: ConcreteClassicalType) -> str:
|
150
|
+
if isinstance(classical_type, StructMetaType):
|
151
|
+
type_name = "Struct"
|
152
|
+
else:
|
153
|
+
type_name = get_qmod_type(classical_type).__name__
|
154
|
+
if not isinstance(classical_type, TypeName):
|
155
|
+
return type_name
|
156
|
+
if type_name not in QMODULE.type_decls and type_name not in QMODULE.enum_decls:
|
157
|
+
raise ClassiqExpansionError(f"Undefined type {type_name}")
|
158
|
+
return type_name
|
@@ -0,0 +1,42 @@
|
|
1
|
+
from collections.abc import Sequence
|
2
|
+
|
3
|
+
from classiq.interface.generator.functions.port_declaration import (
|
4
|
+
PortDeclarationDirection,
|
5
|
+
)
|
6
|
+
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
7
|
+
from classiq.interface.model.quantum_function_declaration import AnonPositionalArg
|
8
|
+
|
9
|
+
from classiq.model_expansions.evaluators.quantum_type_utils import copy_type_information
|
10
|
+
from classiq.model_expansions.scope import Evaluated, QuantumSymbol
|
11
|
+
|
12
|
+
|
13
|
+
def add_information_from_output_arguments(
|
14
|
+
parameters: Sequence[AnonPositionalArg],
|
15
|
+
args: list[Evaluated],
|
16
|
+
) -> list[Evaluated]:
|
17
|
+
"""
|
18
|
+
This function propagates the quantum type information from the output arguments
|
19
|
+
to the arguments that were passed to it.
|
20
|
+
Example:
|
21
|
+
...
|
22
|
+
p = QArray("p", QBit)
|
23
|
+
allocate(4, p)
|
24
|
+
other statements with p...
|
25
|
+
|
26
|
+
In the other statements with p, the size of 4 will be part of p's type info.
|
27
|
+
"""
|
28
|
+
for parameter, argument in zip(parameters, args):
|
29
|
+
if not isinstance(parameter, AnonPortDeclaration):
|
30
|
+
continue
|
31
|
+
|
32
|
+
argument_as_quantum_symbol = argument.as_type(QuantumSymbol)
|
33
|
+
|
34
|
+
if parameter.direction != PortDeclarationDirection.Output:
|
35
|
+
continue
|
36
|
+
|
37
|
+
copy_type_information(
|
38
|
+
parameter.quantum_type,
|
39
|
+
argument_as_quantum_symbol.quantum_type,
|
40
|
+
str(argument_as_quantum_symbol.handle),
|
41
|
+
)
|
42
|
+
return args
|
@@ -0,0 +1,36 @@
|
|
1
|
+
from typing import get_args
|
2
|
+
|
3
|
+
from classiq.interface.generator.expressions.evaluated_expression import (
|
4
|
+
EvaluatedExpression,
|
5
|
+
)
|
6
|
+
from classiq.interface.generator.expressions.expression import Expression
|
7
|
+
from classiq.interface.generator.expressions.expression_types import ExpressionValue
|
8
|
+
from classiq.interface.model.handle_binding import HandleBinding
|
9
|
+
|
10
|
+
from classiq.model_expansions.expression_evaluator import evaluate
|
11
|
+
from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
|
12
|
+
|
13
|
+
|
14
|
+
def evaluate_classical_expression(expr: Expression, scope: Scope) -> Evaluated:
|
15
|
+
all_symbols = scope.items()
|
16
|
+
locals_dict = {
|
17
|
+
name: EvaluatedExpression(value=evaluated.value)
|
18
|
+
for name, evaluated in all_symbols
|
19
|
+
if isinstance(evaluated.value, get_args(ExpressionValue))
|
20
|
+
} | {
|
21
|
+
name: EvaluatedExpression(
|
22
|
+
value=evaluated.value.quantum_type.get_proxy(HandleBinding(name=name))
|
23
|
+
)
|
24
|
+
for name, evaluated in all_symbols
|
25
|
+
if isinstance(evaluated.value, QuantumSymbol)
|
26
|
+
and evaluated.value.quantum_type.has_size_in_bits
|
27
|
+
}
|
28
|
+
uninitialized_locals = {
|
29
|
+
name
|
30
|
+
for name, evaluated in all_symbols
|
31
|
+
if isinstance(evaluated.value, QuantumSymbol)
|
32
|
+
and not evaluated.value.quantum_type.has_size_in_bits
|
33
|
+
}
|
34
|
+
|
35
|
+
ret = evaluate(expr, locals_dict, uninitialized_locals)
|
36
|
+
return Evaluated(value=ret.value)
|
@@ -0,0 +1,144 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from sympy import Equality
|
4
|
+
from sympy.core.numbers import Number
|
5
|
+
|
6
|
+
from classiq.interface.exceptions import ClassiqExpansionError
|
7
|
+
from classiq.interface.generator.expressions.qmod_qscalar_proxy import (
|
8
|
+
QmodQNumProxy,
|
9
|
+
QmodQScalarProxy,
|
10
|
+
QmodSizedProxy,
|
11
|
+
)
|
12
|
+
|
13
|
+
CONTROL_INOUT_NAME = "ctrl"
|
14
|
+
|
15
|
+
|
16
|
+
def type_name(obj: Any) -> str:
|
17
|
+
if isinstance(obj, QmodSizedProxy):
|
18
|
+
return obj.type_name
|
19
|
+
return type(obj).__name__
|
20
|
+
|
21
|
+
|
22
|
+
def resolve_num_condition(condition: Equality) -> tuple[QmodSizedProxy, str]:
|
23
|
+
ctrl, ctrl_val = condition.args
|
24
|
+
if isinstance(ctrl, Number) and isinstance(ctrl_val, QmodQScalarProxy):
|
25
|
+
ctrl, ctrl_val = ctrl_val, ctrl
|
26
|
+
if not isinstance(ctrl, QmodSizedProxy) or not (isinstance(ctrl_val, Number)):
|
27
|
+
_raise_numeric_condition_error(ctrl, ctrl_val)
|
28
|
+
return ctrl, _calculate_ctrl_state(ctrl, float(ctrl_val))
|
29
|
+
|
30
|
+
|
31
|
+
def _calculate_ctrl_state(ctrl: QmodSizedProxy, ctrl_val: float) -> str:
|
32
|
+
is_signed, fraction_places = _get_numeric_attributes(ctrl)
|
33
|
+
|
34
|
+
integer_ctrl_val = _get_integer_ctrl_val(ctrl, ctrl_val, fraction_places)
|
35
|
+
|
36
|
+
_validate_control_value_sign(ctrl, integer_ctrl_val, is_signed)
|
37
|
+
_validate_control_var_qubits(
|
38
|
+
ctrl, integer_ctrl_val, is_signed, fraction_places, ctrl_val
|
39
|
+
)
|
40
|
+
|
41
|
+
return _to_twos_complement(integer_ctrl_val, ctrl.size)
|
42
|
+
|
43
|
+
|
44
|
+
def _get_numeric_attributes(ctrl: QmodSizedProxy) -> tuple[bool, int]:
|
45
|
+
return (
|
46
|
+
(ctrl.is_signed, ctrl.fraction_digits)
|
47
|
+
if isinstance(ctrl, QmodQNumProxy)
|
48
|
+
else (False, 0)
|
49
|
+
)
|
50
|
+
|
51
|
+
|
52
|
+
def _get_integer_ctrl_val(
|
53
|
+
ctrl: QmodSizedProxy, ctrl_val: float, fraction_places: int
|
54
|
+
) -> int:
|
55
|
+
unfractioned_ctrl_val = ctrl_val * 2**fraction_places
|
56
|
+
if unfractioned_ctrl_val != int(unfractioned_ctrl_val):
|
57
|
+
raise ClassiqExpansionError(
|
58
|
+
f"Variable {str(ctrl)!r} doesne't have enough fraction digits to "
|
59
|
+
f"represent control value {ctrl_val}"
|
60
|
+
)
|
61
|
+
return int(unfractioned_ctrl_val)
|
62
|
+
|
63
|
+
|
64
|
+
def _validate_control_value_sign(
|
65
|
+
ctrl: QmodSizedProxy, ctrl_val: int, is_signed: bool
|
66
|
+
) -> None:
|
67
|
+
if not is_signed and ctrl_val < 0:
|
68
|
+
raise ClassiqExpansionError(
|
69
|
+
f"Variable {str(ctrl)!r} is not signed but control value "
|
70
|
+
f"{ctrl_val} is negative"
|
71
|
+
)
|
72
|
+
|
73
|
+
|
74
|
+
def _validate_control_var_qubits(
|
75
|
+
ctrl: QmodSizedProxy,
|
76
|
+
ctrl_val: int,
|
77
|
+
is_signed: bool,
|
78
|
+
fraction_places: int,
|
79
|
+
orig_ctrl_val: float,
|
80
|
+
) -> None:
|
81
|
+
required_qubits = _min_bit_length(ctrl_val, is_signed)
|
82
|
+
fraction_places_message = (
|
83
|
+
f" with {fraction_places} fraction digits" if fraction_places else ""
|
84
|
+
)
|
85
|
+
if ctrl.size < required_qubits:
|
86
|
+
raise ClassiqExpansionError(
|
87
|
+
f"Variable {str(ctrl)!r} has {ctrl.size} qubits{fraction_places_message} but control value "
|
88
|
+
f"{str(orig_ctrl_val if fraction_places else ctrl_val)!r} requires at least {required_qubits} qubits{fraction_places_message}"
|
89
|
+
)
|
90
|
+
|
91
|
+
|
92
|
+
def _raise_numeric_condition_error(ctrl: Any, ctrl_val: Any) -> None:
|
93
|
+
message = (
|
94
|
+
"Control condition must be of the form '<quantum-variable> == "
|
95
|
+
"<classical-number-expression>' or vice versa. "
|
96
|
+
)
|
97
|
+
prefix = f"Neither {ctrl!r} (type {type_name(ctrl)}) or {ctrl_val!r} (type {type_name(ctrl_val)}) is a "
|
98
|
+
if not isinstance(ctrl, QmodSizedProxy) and not isinstance(
|
99
|
+
ctrl_val, QmodSizedProxy
|
100
|
+
):
|
101
|
+
message += prefix + "quantum variable."
|
102
|
+
elif not isinstance(ctrl, Number) and not isinstance(ctrl_val, Number):
|
103
|
+
message += prefix + "classical number."
|
104
|
+
raise ClassiqExpansionError(message)
|
105
|
+
|
106
|
+
|
107
|
+
def _min_unsigned_bit_length(number: int) -> int:
|
108
|
+
if number < 0:
|
109
|
+
raise ClassiqExpansionError(
|
110
|
+
f"Quantum register is not signed but control value "
|
111
|
+
f"'{number}' is negative"
|
112
|
+
)
|
113
|
+
try:
|
114
|
+
return 1 if number == 0 else number.bit_length()
|
115
|
+
except AttributeError as e:
|
116
|
+
raise e
|
117
|
+
|
118
|
+
|
119
|
+
def _min_signed_bit_length(number: int) -> int:
|
120
|
+
pos_val = abs(number)
|
121
|
+
is_whole = pos_val & (pos_val - 1) == 0
|
122
|
+
if number <= 0 and is_whole:
|
123
|
+
return _min_unsigned_bit_length(pos_val)
|
124
|
+
return _min_unsigned_bit_length(pos_val) + 1
|
125
|
+
|
126
|
+
|
127
|
+
def _min_bit_length(number: int, is_signed: bool) -> int:
|
128
|
+
return (
|
129
|
+
_min_signed_bit_length(number)
|
130
|
+
if is_signed
|
131
|
+
else _min_unsigned_bit_length(number)
|
132
|
+
)
|
133
|
+
|
134
|
+
|
135
|
+
def _to_twos_complement(value: int, bits: int) -> str:
|
136
|
+
if value >= 0:
|
137
|
+
return bin(value)[2:].zfill(bits)[::-1]
|
138
|
+
return _to_negative_twos_complement(value, bits)
|
139
|
+
|
140
|
+
|
141
|
+
def _to_negative_twos_complement(value: int, bits: int) -> str:
|
142
|
+
mask = (1 << bits) - 1
|
143
|
+
value = (abs(value) ^ mask) + 1
|
144
|
+
return bin(value)[:1:-1].rjust(bits, "1")
|