classiq 0.37.1__py3-none-any.whl → 0.65.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/__init__.py +49 -34
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +3 -2
- classiq/_analyzer_extras/interactive_hardware.py +3 -3
- classiq/_internals/api_wrapper.py +241 -95
- classiq/_internals/async_utils.py +2 -77
- classiq/_internals/authentication/auth0.py +26 -10
- classiq/_internals/authentication/authentication.py +11 -0
- classiq/_internals/authentication/device.py +18 -8
- classiq/_internals/authentication/password_manager.py +40 -13
- classiq/_internals/authentication/token_manager.py +11 -6
- classiq/_internals/client.py +106 -37
- classiq/_internals/config.py +3 -4
- classiq/_internals/host_checker.py +38 -15
- classiq/_internals/jobs.py +56 -50
- classiq/_internals/type_validation.py +9 -9
- classiq/analyzer/__init__.py +1 -3
- classiq/analyzer/analyzer.py +50 -47
- classiq/analyzer/analyzer_utilities.py +15 -15
- classiq/analyzer/rb.py +19 -20
- classiq/analyzer/show_interactive_hack.py +30 -7
- classiq/analyzer/url_utils.py +2 -3
- classiq/applications/__init__.py +3 -12
- classiq/applications/chemistry/__init__.py +14 -10
- classiq/applications/chemistry/ansatz_parameters.py +4 -4
- classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +170 -170
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/applications/combinatorial_helpers/allowed_constraints.py +23 -0
- classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
- classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +166 -0
- classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
- classiq/applications/combinatorial_helpers/encoding_utils.py +124 -0
- classiq/applications/combinatorial_helpers/memory.py +75 -0
- classiq/applications/combinatorial_helpers/optimization_model.py +193 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
- classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
- classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
- classiq/applications/combinatorial_helpers/transformations/encoding.py +189 -0
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +143 -0
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +120 -0
- classiq/applications/combinatorial_helpers/transformations/penalty.py +31 -0
- classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
- classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +74 -0
- classiq/applications/combinatorial_helpers/transformations/slack_variables.py +87 -0
- classiq/applications/combinatorial_optimization/__init__.py +24 -5
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +137 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
- classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
- classiq/applications/finance/__init__.py +4 -5
- classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +50 -57
- classiq/applications/grover/__init__.py +9 -0
- classiq/applications/grover/grover_model_constructor.py +157 -0
- classiq/applications/hamiltonian/__init__.py +0 -0
- classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
- classiq/applications/libraries/__init__.py +0 -0
- classiq/applications/libraries/qmci_library.py +22 -0
- classiq/applications/qnn/__init__.py +2 -4
- classiq/applications/qnn/circuit_utils.py +8 -8
- classiq/applications/qnn/datasets/__init__.py +9 -11
- classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
- classiq/applications/qnn/datasets/dataset_not.py +2 -1
- classiq/applications/qnn/datasets/dataset_parity.py +2 -2
- classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
- classiq/applications/qnn/qlayer.py +30 -10
- classiq/applications/qnn/torch_utils.py +4 -3
- classiq/applications/qnn/types.py +7 -7
- classiq/applications/qsvm/__init__.py +6 -4
- classiq/applications/qsvm/qsvm.py +4 -10
- classiq/applications/qsvm/qsvm_data_generation.py +5 -8
- classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
- classiq/execution/__init__.py +8 -3
- classiq/execution/all_hardware_devices.py +11 -0
- classiq/execution/execution_session.py +400 -0
- classiq/execution/iqcc.py +63 -0
- classiq/execution/jobs.py +197 -25
- classiq/execution/qnn.py +79 -0
- classiq/executor.py +23 -117
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +49 -16
- classiq/interface/analyzer/cytoscape_graph.py +15 -9
- classiq/interface/analyzer/result.py +36 -32
- classiq/interface/applications/qsvm.py +28 -25
- classiq/interface/ast_node.py +16 -0
- classiq/interface/backend/backend_preferences.py +390 -119
- classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
- classiq/interface/backend/pydantic_backend.py +27 -22
- classiq/interface/backend/quantum_backend_providers.py +70 -16
- classiq/interface/chemistry/fermionic_operator.py +43 -32
- classiq/interface/chemistry/ground_state_problem.py +42 -24
- classiq/interface/chemistry/molecule.py +20 -14
- classiq/interface/chemistry/operator.py +75 -236
- classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +2 -4
- classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
- classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
- classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
- classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
- classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
- classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
- classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
- classiq/interface/combinatorial_optimization/examples/set_cover.py +3 -3
- classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +14 -9
- classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
- classiq/interface/combinatorial_optimization/result.py +1 -3
- classiq/interface/combinatorial_optimization/solver_types.py +1 -1
- classiq/interface/debug_info/__init__.py +0 -0
- classiq/interface/debug_info/debug_info.py +86 -0
- classiq/interface/exceptions.py +201 -0
- classiq/interface/execution/iqcc.py +19 -0
- classiq/interface/execution/jobs.py +15 -12
- classiq/interface/execution/primitives.py +18 -0
- classiq/interface/executor/constants.py +1 -0
- classiq/interface/executor/estimation.py +2 -2
- classiq/interface/executor/execution_preferences.py +26 -143
- classiq/interface/executor/execution_request.py +36 -56
- classiq/interface/executor/execution_result.py +30 -8
- classiq/interface/executor/iqae_result.py +4 -6
- classiq/interface/executor/optimizer_preferences.py +34 -22
- classiq/interface/executor/{quantum_program.py → quantum_code.py} +44 -34
- classiq/interface/executor/quantum_instruction_set.py +3 -2
- classiq/interface/executor/register_initialization.py +12 -17
- classiq/interface/executor/result.py +122 -64
- classiq/interface/executor/vqe_result.py +11 -11
- classiq/interface/finance/function_input.py +42 -19
- classiq/interface/finance/gaussian_model_input.py +7 -5
- classiq/interface/finance/log_normal_model_input.py +6 -4
- classiq/interface/finance/model_input.py +6 -4
- classiq/interface/generator/adjacency.py +1 -3
- classiq/interface/generator/amplitude_loading.py +27 -14
- classiq/interface/generator/ansatz_library.py +5 -5
- classiq/interface/generator/application_apis/__init__.py +1 -0
- classiq/interface/generator/application_apis/arithmetic_declarations.py +17 -0
- classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
- classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
- classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
- classiq/interface/generator/application_apis/finance_declarations.py +48 -69
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
- classiq/interface/generator/arith/argument_utils.py +57 -6
- classiq/interface/generator/arith/arithmetic.py +37 -16
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +15 -17
- classiq/interface/generator/arith/arithmetic_expression_abc.py +70 -26
- classiq/interface/generator/arith/arithmetic_expression_parser.py +18 -12
- classiq/interface/generator/arith/arithmetic_expression_validator.py +61 -43
- classiq/interface/generator/arith/arithmetic_operations.py +19 -16
- classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
- classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
- classiq/interface/generator/arith/ast_node_rewrite.py +4 -3
- classiq/interface/generator/arith/binary_ops.py +375 -139
- classiq/interface/generator/arith/endianness.py +1 -1
- classiq/interface/generator/arith/extremum_operations.py +96 -23
- classiq/interface/generator/arith/logical_ops.py +16 -12
- classiq/interface/generator/arith/machine_precision.py +3 -0
- classiq/interface/generator/arith/number_utils.py +44 -48
- classiq/interface/generator/arith/register_user_input.py +70 -27
- classiq/interface/generator/arith/unary_ops.py +57 -46
- classiq/interface/generator/arith/uncomputation_methods.py +1 -1
- classiq/interface/generator/builtin_api_builder.py +2 -9
- classiq/interface/generator/chemistry_function_params.py +5 -5
- classiq/interface/generator/circuit_code/circuit_code.py +7 -7
- classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
- classiq/interface/generator/commuting_pauli_exponentiation.py +8 -6
- classiq/interface/generator/compiler_keywords.py +8 -0
- classiq/interface/generator/complex_type.py +13 -25
- classiq/interface/generator/constant.py +3 -4
- classiq/interface/generator/control_state.py +35 -28
- classiq/interface/generator/copy.py +47 -0
- classiq/interface/generator/custom_ansatz.py +2 -5
- classiq/interface/generator/distance.py +3 -5
- classiq/interface/generator/excitations.py +3 -2
- classiq/interface/generator/expressions/atomic_expression_functions.py +26 -8
- classiq/interface/generator/expressions/enums/__init__.py +0 -10
- classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
- classiq/interface/generator/expressions/evaluated_expression.py +21 -7
- classiq/interface/generator/expressions/expression.py +27 -15
- classiq/interface/generator/expressions/expression_constants.py +9 -3
- classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +59 -0
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
- classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
- classiq/interface/generator/expressions/sympy_supported_expressions.py +20 -11
- classiq/interface/generator/finance.py +3 -3
- classiq/interface/generator/function_param_library.py +6 -6
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
- classiq/interface/generator/function_params.py +42 -69
- classiq/interface/generator/functions/__init__.py +0 -22
- classiq/interface/generator/functions/builtins/__init__.py +0 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
- classiq/interface/generator/functions/classical_function_declaration.py +18 -9
- classiq/interface/generator/functions/classical_type.py +47 -166
- classiq/interface/generator/functions/concrete_types.py +55 -0
- classiq/interface/generator/functions/function_declaration.py +13 -14
- classiq/interface/generator/functions/port_declaration.py +1 -13
- classiq/interface/generator/functions/qmod_python_interface.py +2 -1
- classiq/interface/generator/functions/type_name.py +90 -0
- classiq/interface/generator/generated_circuit_data.py +155 -22
- classiq/interface/generator/grover_diffuser.py +32 -25
- classiq/interface/generator/grover_operator.py +34 -23
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +12 -8
- classiq/interface/generator/hardware/hardware_data.py +76 -36
- classiq/interface/generator/hardware_efficient_ansatz.py +38 -17
- classiq/interface/generator/hartree_fock.py +14 -4
- classiq/interface/generator/identity.py +10 -6
- classiq/interface/generator/linear_pauli_rotations.py +33 -19
- classiq/interface/generator/mcmt_method.py +1 -1
- classiq/interface/generator/mcu.py +20 -16
- classiq/interface/generator/mcx.py +29 -20
- classiq/interface/generator/model/__init__.py +2 -5
- classiq/interface/generator/model/constraints.py +27 -8
- classiq/interface/generator/model/model.py +32 -203
- classiq/interface/generator/model/preferences/preferences.py +118 -43
- classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +27 -22
- classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
- classiq/interface/generator/oracles/custom_oracle.py +17 -13
- classiq/interface/generator/oracles/oracle_abc.py +9 -9
- classiq/interface/generator/partitioned_register.py +7 -7
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
- classiq/interface/generator/preferences/optimization.py +1 -2
- classiq/interface/generator/qpe.py +47 -34
- classiq/interface/generator/qsvm.py +13 -17
- classiq/interface/generator/quantum_function_call.py +107 -87
- classiq/interface/generator/{generated_circuit.py → quantum_program.py} +50 -37
- classiq/interface/generator/range_types.py +13 -12
- classiq/interface/generator/register_role.py +18 -6
- classiq/interface/generator/slice_parsing_utils.py +11 -6
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +32 -39
- classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
- classiq/interface/generator/standard_gates/standard_gates.py +3 -3
- classiq/interface/generator/standard_gates/u_gate.py +7 -10
- classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
- classiq/interface/generator/state_preparation/distributions.py +16 -15
- classiq/interface/generator/state_preparation/metrics.py +5 -7
- classiq/interface/generator/state_preparation/state_preparation.py +30 -23
- classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
- classiq/interface/generator/transpiler_basis_gates.py +7 -3
- classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
- classiq/interface/generator/types/compilation_metadata.py +6 -0
- classiq/interface/generator/types/enum_declaration.py +54 -0
- classiq/interface/generator/types/qstruct_declaration.py +18 -0
- classiq/interface/generator/types/struct_declaration.py +15 -14
- classiq/interface/generator/ucc.py +9 -6
- classiq/interface/generator/unitary_gate.py +10 -6
- classiq/interface/generator/user_defined_function_params.py +4 -1
- classiq/interface/generator/validations/flow_graph.py +11 -9
- classiq/interface/generator/validations/validator_functions.py +8 -6
- classiq/interface/generator/visitor.py +23 -16
- classiq/interface/hardware.py +31 -10
- classiq/interface/helpers/classproperty.py +8 -0
- classiq/interface/helpers/custom_encoders.py +3 -0
- classiq/interface/helpers/custom_pydantic_types.py +40 -50
- classiq/interface/helpers/datastructures.py +26 -0
- classiq/interface/helpers/hashable_mixin.py +3 -2
- classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
- classiq/interface/helpers/pydantic_model_helpers.py +7 -11
- classiq/interface/helpers/validation_helpers.py +4 -21
- classiq/interface/helpers/versioned_model.py +1 -1
- classiq/interface/ide/ide_data.py +16 -20
- classiq/interface/ide/visual_model.py +130 -0
- classiq/interface/interface_version.py +1 -0
- classiq/interface/jobs.py +35 -6
- classiq/interface/model/allocate.py +16 -0
- classiq/interface/model/bind_operation.py +44 -14
- classiq/interface/model/classical_if.py +15 -0
- classiq/interface/model/classical_parameter_declaration.py +33 -3
- classiq/interface/model/control.py +45 -0
- classiq/interface/model/handle_binding.py +298 -20
- classiq/interface/model/inplace_binary_operation.py +31 -26
- classiq/interface/model/invert.py +12 -0
- classiq/interface/model/model.py +87 -73
- classiq/interface/model/native_function_definition.py +16 -21
- classiq/interface/model/parameter.py +13 -0
- classiq/interface/model/phase_operation.py +11 -0
- classiq/interface/model/port_declaration.py +27 -9
- classiq/interface/model/power.py +14 -0
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +38 -21
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
- classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
- classiq/interface/model/quantum_function_call.py +146 -462
- classiq/interface/model/quantum_function_declaration.py +193 -152
- classiq/interface/model/quantum_lambda_function.py +65 -0
- classiq/interface/model/quantum_statement.py +71 -12
- classiq/interface/model/quantum_type.py +205 -67
- classiq/interface/model/quantum_variable_declaration.py +4 -26
- classiq/interface/model/repeat.py +15 -0
- classiq/interface/model/statement_block.py +58 -0
- classiq/interface/model/validation_handle.py +13 -6
- classiq/interface/model/variable_declaration_statement.py +3 -1
- classiq/interface/model/within_apply_operation.py +13 -0
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
- classiq/interface/server/global_versions.py +6 -7
- classiq/interface/server/routes.py +22 -21
- classiq/interface/source_reference.py +59 -0
- classiq/model_expansions/__init__.py +0 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
- classiq/model_expansions/capturing/__init__.py +0 -0
- classiq/model_expansions/capturing/captured_vars.py +435 -0
- classiq/model_expansions/capturing/mangling_utils.py +56 -0
- classiq/model_expansions/closure.py +171 -0
- classiq/model_expansions/debug_flag.py +3 -0
- classiq/model_expansions/evaluators/__init__.py +0 -0
- classiq/model_expansions/evaluators/arg_type_match.py +158 -0
- classiq/model_expansions/evaluators/argument_types.py +42 -0
- classiq/model_expansions/evaluators/classical_expression.py +36 -0
- classiq/model_expansions/evaluators/control.py +144 -0
- classiq/model_expansions/evaluators/parameter_types.py +226 -0
- classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
- classiq/model_expansions/evaluators/type_type_match.py +90 -0
- classiq/model_expansions/expression_evaluator.py +135 -0
- classiq/model_expansions/expression_renamer.py +76 -0
- classiq/model_expansions/function_builder.py +247 -0
- classiq/model_expansions/generative_functions.py +158 -0
- classiq/model_expansions/interpreters/__init__.py +0 -0
- classiq/model_expansions/interpreters/base_interpreter.py +263 -0
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
- classiq/model_expansions/model_tables.py +18 -0
- classiq/model_expansions/quantum_operations/__init__.py +9 -0
- classiq/model_expansions/quantum_operations/bind.py +60 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
- classiq/model_expansions/quantum_operations/classicalif.py +53 -0
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
- classiq/model_expansions/quantum_operations/emitter.py +181 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
- classiq/model_expansions/quantum_operations/repeat.py +56 -0
- classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
- classiq/model_expansions/scope.py +240 -0
- classiq/model_expansions/scope_initialization.py +150 -0
- classiq/model_expansions/sympy_conversion/__init__.py +0 -0
- classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
- classiq/model_expansions/transformers/__init__.py +0 -0
- classiq/model_expansions/transformers/ast_renamer.py +26 -0
- classiq/model_expansions/transformers/var_splitter.py +299 -0
- classiq/model_expansions/utils/__init__.py +0 -0
- classiq/model_expansions/utils/counted_name_allocator.py +11 -0
- classiq/model_expansions/utils/handles_collector.py +33 -0
- classiq/model_expansions/visitors/__init__.py +0 -0
- classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
- classiq/model_expansions/visitors/variable_references.py +144 -0
- classiq/open_library/__init__.py +4 -0
- classiq/open_library/functions/__init__.py +130 -0
- classiq/open_library/functions/amplitude_estimation.py +30 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
- classiq/open_library/functions/grover.py +157 -0
- classiq/open_library/functions/hea.py +115 -0
- classiq/open_library/functions/linear_pauli_rotation.py +82 -0
- classiq/open_library/functions/modular_exponentiation.py +201 -0
- classiq/open_library/functions/qaoa_penalty.py +117 -0
- classiq/open_library/functions/qft_functions.py +54 -0
- classiq/open_library/functions/qpe.py +46 -0
- classiq/open_library/functions/qsvt.py +331 -0
- classiq/open_library/functions/state_preparation.py +301 -0
- classiq/open_library/functions/swap_test.py +27 -0
- classiq/open_library/functions/utility_functions.py +81 -0
- classiq/open_library/functions/variational.py +52 -0
- classiq/qmod/__init__.py +17 -10
- classiq/qmod/builtins/__init__.py +19 -2
- classiq/qmod/builtins/classical_execution_primitives.py +60 -47
- classiq/qmod/builtins/classical_functions.py +44 -38
- classiq/qmod/builtins/constants.py +10 -0
- classiq/qmod/builtins/enums.py +208 -0
- classiq/qmod/builtins/functions/__init__.py +137 -0
- classiq/qmod/builtins/functions/allocation.py +150 -0
- classiq/qmod/builtins/functions/arithmetic.py +55 -0
- classiq/qmod/builtins/functions/benchmarking.py +8 -0
- classiq/qmod/builtins/functions/chemistry.py +91 -0
- classiq/qmod/builtins/functions/exponentiation.py +105 -0
- classiq/qmod/builtins/functions/finance.py +34 -0
- classiq/qmod/builtins/functions/operators.py +16 -0
- classiq/qmod/builtins/functions/qsvm.py +24 -0
- classiq/qmod/builtins/functions/standard_gates.py +651 -0
- classiq/qmod/builtins/operations.py +379 -57
- classiq/qmod/builtins/structs.py +103 -80
- classiq/qmod/cfunc.py +42 -0
- classiq/qmod/classical_function.py +8 -20
- classiq/qmod/cparam.py +64 -0
- classiq/qmod/create_model_function.py +56 -0
- classiq/qmod/declaration_inferrer.py +145 -112
- classiq/qmod/expression_query.py +39 -0
- classiq/qmod/generative.py +42 -0
- classiq/qmod/model_state_container.py +19 -5
- classiq/qmod/native/__init__.py +7 -0
- classiq/qmod/native/expression_to_qmod.py +194 -0
- classiq/qmod/native/pretty_printer.py +401 -0
- classiq/qmod/pretty_print/__init__.py +7 -0
- classiq/qmod/pretty_print/expression_to_python.py +222 -0
- classiq/qmod/pretty_print/pretty_printer.py +572 -0
- classiq/qmod/python_classical_type.py +67 -0
- classiq/qmod/qfunc.py +79 -0
- classiq/qmod/qmod_constant.py +143 -0
- classiq/qmod/qmod_parameter.py +84 -53
- classiq/qmod/qmod_variable.py +497 -100
- classiq/qmod/quantum_callable.py +17 -7
- classiq/qmod/quantum_expandable.py +278 -105
- classiq/qmod/quantum_function.py +232 -48
- classiq/qmod/semantics/__init__.py +0 -0
- classiq/qmod/semantics/annotation/__init__.py +0 -0
- classiq/qmod/semantics/annotation/call_annotation.py +92 -0
- classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
- classiq/qmod/semantics/error_manager.py +88 -0
- classiq/qmod/semantics/lambdas.py +25 -0
- classiq/qmod/semantics/static_semantics_visitor.py +384 -0
- classiq/qmod/semantics/validation/__init__.py +0 -0
- classiq/qmod/semantics/validation/constants_validation.py +16 -0
- classiq/qmod/semantics/validation/func_call_validation.py +99 -0
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
- classiq/qmod/semantics/validation/handle_validation.py +85 -0
- classiq/qmod/semantics/validation/main_validation.py +33 -0
- classiq/qmod/semantics/validation/types_validation.py +128 -0
- classiq/qmod/symbolic.py +178 -111
- classiq/qmod/symbolic_expr.py +36 -12
- classiq/qmod/symbolic_type.py +2 -5
- classiq/qmod/type_attribute_remover.py +32 -0
- classiq/qmod/utilities.py +108 -1
- classiq/qmod/write_qmod.py +53 -0
- classiq/synthesis.py +210 -22
- {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -8
- classiq-0.65.3.dist-info/RECORD +521 -0
- {classiq-0.37.1.dist-info → classiq-0.65.3.dist-info}/WHEEL +1 -1
- classiq/_internals/_qfunc_ext.py +0 -6
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -17
- classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
- classiq/applications_model_constructors/grover_model_constructor.py +0 -227
- classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
- classiq/builtin_functions/__init__.py +0 -43
- classiq/builtin_functions/amplitude_loading.py +0 -3
- classiq/builtin_functions/binary_ops.py +0 -1
- classiq/builtin_functions/exponentiation.py +0 -5
- classiq/builtin_functions/qpe.py +0 -4
- classiq/builtin_functions/qsvm.py +0 -7
- classiq/builtin_functions/range_types.py +0 -5
- classiq/builtin_functions/standard_gates.py +0 -1
- classiq/builtin_functions/state_preparation.py +0 -6
- classiq/builtin_functions/suzuki_trotter.py +0 -3
- classiq/exceptions.py +0 -131
- classiq/interface/executor/aws_execution_cost.py +0 -72
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/credit_risk_example/linear_gci.py +0 -115
- classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -59
- classiq/interface/generator/expressions/enums/chemistry.py +0 -28
- classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
- classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
- classiq/interface/generator/expressions/enums/optimizers.py +0 -9
- classiq/interface/generator/expressions/enums/pauli.py +0 -8
- classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
- classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -862
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
- classiq/interface/generator/functions/foreign_function_definition.py +0 -106
- classiq/interface/generator/functions/function_implementation.py +0 -103
- classiq/interface/generator/functions/native_function_definition.py +0 -153
- classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
- classiq/interface/generator/functions/register.py +0 -42
- classiq/interface/generator/functions/register_mapping_data.py +0 -102
- classiq/interface/generator/inequality_mixer.py +0 -51
- classiq/interface/generator/model/classical_main_validator.py +0 -106
- classiq/interface/generator/range_mixer.py +0 -56
- classiq/interface/generator/state_propagator.py +0 -63
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -2
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
- classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
- classiq/interface/generator/types/combinatorial_problem.py +0 -26
- classiq/interface/ide/show.py +0 -34
- classiq/interface/model/common_model_types.py +0 -23
- classiq/interface/model/numeric_reinterpretation.py +0 -25
- classiq/interface/model/operator_synthesis_data.py +0 -48
- classiq/interface/model/quantum_expressions/control_state.py +0 -38
- classiq/interface/model/quantum_if_operation.py +0 -95
- classiq/interface/model/resolvers/function_call_resolver.py +0 -43
- classiq/interface/model/validations/handle_validation_base.py +0 -55
- classiq/interface/model/validations/handles_validator.py +0 -154
- classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
- classiq/model/__init__.py +0 -14
- classiq/model/composite_function_generator.py +0 -33
- classiq/model/function_handler.py +0 -466
- classiq/model/function_handler.pyi +0 -152
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -246
- classiq/qmod/builtins/functions.py +0 -896
- classiq/qmod/qmod_struct.py +0 -37
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -207
- classiq/quantum_functions/decorators.py +0 -22
- classiq/quantum_functions/function_library.py +0 -181
- classiq/quantum_functions/function_parser.py +0 -74
- classiq/quantum_functions/quantum_function.py +0 -236
- classiq-0.37.1.dist-info/RECORD +0 -418
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
- /classiq/{interface/generator/credit_risk_example → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/pauli_helpers}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/py.typed} +0 -0
- /classiq/{interface/model/resolvers → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
- /classiq/{interface/model/validations → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
- /classiq/{_internals → interface}/enum_utils.py +0 -0
@@ -1,23 +1,29 @@
|
|
1
1
|
import math
|
2
|
+
from collections.abc import Iterable
|
2
3
|
from typing import (
|
3
4
|
Any,
|
4
5
|
ClassVar,
|
5
|
-
Dict,
|
6
6
|
Generic,
|
7
|
-
Iterable,
|
8
7
|
Literal,
|
9
8
|
Optional,
|
10
|
-
Tuple,
|
11
9
|
TypeVar,
|
12
10
|
Union,
|
13
11
|
)
|
14
12
|
|
15
13
|
import pydantic
|
16
|
-
from pydantic
|
14
|
+
from pydantic import BaseModel
|
15
|
+
from pydantic_core.core_schema import ValidationInfo
|
16
|
+
from typing_extensions import Self
|
17
17
|
|
18
|
+
from classiq.interface.enum_utils import StrEnum
|
19
|
+
from classiq.interface.exceptions import ClassiqValueError
|
18
20
|
from classiq.interface.generator.arith import argument_utils, number_utils
|
19
|
-
from classiq.interface.generator.arith.argument_utils import
|
21
|
+
from classiq.interface.generator.arith.argument_utils import (
|
22
|
+
RegisterOrConst,
|
23
|
+
as_arithmetic_info,
|
24
|
+
)
|
20
25
|
from classiq.interface.generator.arith.arithmetic_operations import (
|
26
|
+
MODULO_WITH_FRACTION_PLACES_ERROR_MSG,
|
21
27
|
ArithmeticOperationParams,
|
22
28
|
)
|
23
29
|
from classiq.interface.generator.arith.ast_node_rewrite import (
|
@@ -27,8 +33,6 @@ from classiq.interface.generator.arith.register_user_input import RegisterArithm
|
|
27
33
|
from classiq.interface.generator.arith.unary_ops import Negation
|
28
34
|
from classiq.interface.generator.function_params import get_zero_input_name
|
29
35
|
|
30
|
-
from classiq._internals.enum_utils import StrEnum
|
31
|
-
|
32
36
|
LeftDataT = TypeVar("LeftDataT")
|
33
37
|
RightDataT = TypeVar("RightDataT")
|
34
38
|
_NumericArgumentInplaceErrorMessage: str = "Cannot inplace the numeric argument {}"
|
@@ -49,35 +53,49 @@ class ArgToInplace(StrEnum):
|
|
49
53
|
|
50
54
|
|
51
55
|
class BinaryOpParams(
|
52
|
-
ArithmeticOperationParams,
|
56
|
+
ArithmeticOperationParams, BaseModel, Generic[LeftDataT, RightDataT]
|
53
57
|
):
|
54
58
|
left_arg: LeftDataT
|
55
59
|
right_arg: RightDataT
|
56
60
|
left_arg_name: ClassVar[str] = DEFAULT_LEFT_ARG_NAME
|
57
61
|
right_arg_name: ClassVar[str] = DEFAULT_RIGHT_ARG_NAME
|
58
62
|
|
59
|
-
@pydantic.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
@pydantic.model_validator(mode="before")
|
64
|
+
@classmethod
|
65
|
+
def _clone_repeated_arg(cls, values: Any) -> dict[str, Any]:
|
66
|
+
if isinstance(values, dict):
|
67
|
+
left_arg = values.get("left_arg")
|
68
|
+
right_arg = values.get("right_arg")
|
69
|
+
|
70
|
+
if left_arg is right_arg and isinstance(left_arg, pydantic.BaseModel):
|
71
|
+
# In case both arguments refer to the same object, copy it.
|
72
|
+
# This prevents changes performed on one argument to affect the other.
|
73
|
+
values["right_arg"] = left_arg.model_copy(deep=True)
|
69
74
|
return values
|
70
75
|
|
76
|
+
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
77
|
+
return 0
|
78
|
+
|
71
79
|
def _create_ios(self) -> None:
|
72
80
|
self._inputs = dict()
|
73
81
|
if isinstance(self.left_arg, RegisterArithmeticInfo):
|
74
82
|
self._inputs[self.left_arg_name] = self.left_arg
|
75
83
|
if isinstance(self.right_arg, RegisterArithmeticInfo):
|
76
84
|
self._inputs[self.right_arg_name] = self.right_arg
|
77
|
-
zero_input_name = get_zero_input_name(self.output_name)
|
78
|
-
self._zero_inputs = {zero_input_name: self.result_register}
|
79
85
|
self._outputs = {**self._inputs, self.output_name: self.result_register}
|
80
86
|
|
87
|
+
garbage_size = self.garbage_output_size()
|
88
|
+
if garbage_size > 0:
|
89
|
+
self._outputs[self.garbage_output_name] = RegisterArithmeticInfo(
|
90
|
+
size=garbage_size
|
91
|
+
)
|
92
|
+
|
93
|
+
zero_input_name = get_zero_input_name(self.output_name)
|
94
|
+
zero_input_size = self.result_register.size + garbage_size
|
95
|
+
self._zero_inputs = {
|
96
|
+
zero_input_name: RegisterArithmeticInfo(size=zero_input_size)
|
97
|
+
}
|
98
|
+
|
81
99
|
def is_inplaced(self) -> bool:
|
82
100
|
return False
|
83
101
|
|
@@ -90,24 +108,25 @@ class InplacableBinaryOpParams(
|
|
90
108
|
):
|
91
109
|
inplace_arg: Optional[ArgToInplace] = None
|
92
110
|
|
93
|
-
@pydantic.
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
111
|
+
@pydantic.model_validator(mode="before")
|
112
|
+
@classmethod
|
113
|
+
def _validate_inplace_arg(cls, values: Any) -> dict[str, Any]:
|
114
|
+
if isinstance(values, dict):
|
115
|
+
left_arg = values.get("left_arg")
|
116
|
+
right_arg = values.get("right_arg")
|
117
|
+
inplace_arg: Optional[ArgToInplace] = values.get("inplace_arg")
|
118
|
+
if inplace_arg == ArgToInplace.RIGHT and isinstance(right_arg, Numeric):
|
119
|
+
raise ClassiqValueError(
|
120
|
+
_NumericArgumentInplaceErrorMessage.format(right_arg)
|
121
|
+
)
|
122
|
+
elif inplace_arg == ArgToInplace.LEFT and isinstance(left_arg, Numeric):
|
123
|
+
raise ClassiqValueError(
|
124
|
+
_NumericArgumentInplaceErrorMessage.format(left_arg)
|
125
|
+
)
|
102
126
|
return values
|
103
127
|
|
104
128
|
def _create_ios(self) -> None:
|
105
129
|
BinaryOpParams._create_ios(self)
|
106
|
-
garbage_size = self.garbage_output_size()
|
107
|
-
if garbage_size > 0:
|
108
|
-
self._outputs[self.garbage_output_name] = RegisterArithmeticInfo(
|
109
|
-
size=garbage_size
|
110
|
-
)
|
111
130
|
if self.inplace_arg is None:
|
112
131
|
return
|
113
132
|
inplace_arg_name = (
|
@@ -117,7 +136,7 @@ class InplacableBinaryOpParams(
|
|
117
136
|
)
|
118
137
|
self._outputs.pop(inplace_arg_name)
|
119
138
|
|
120
|
-
self._set_inplace_zero_inputs(inplace_arg_name,
|
139
|
+
self._set_inplace_zero_inputs(inplace_arg_name, self.garbage_output_size())
|
121
140
|
|
122
141
|
def _set_inplace_zero_inputs(
|
123
142
|
self, inplace_arg_name: str, garbage_size: int
|
@@ -140,9 +159,13 @@ class InplacableBinaryOpParams(
|
|
140
159
|
if self.inplace_arg is None:
|
141
160
|
return 0
|
142
161
|
arg = self.left_arg if self.inplace_arg == ArgToInplace.LEFT else self.right_arg
|
143
|
-
return max(
|
162
|
+
return max(
|
163
|
+
0, arg.integer_part_size - self.result_register.integer_part_size # type: ignore[attr-defined]
|
164
|
+
) + max(
|
165
|
+
0, arg.fraction_places - self.result_register.fraction_places # type: ignore[attr-defined]
|
166
|
+
)
|
144
167
|
|
145
|
-
def _carried_arguments(self) ->
|
168
|
+
def _carried_arguments(self) -> tuple[Optional[LeftDataT], Optional[RightDataT]]:
|
146
169
|
if self.inplace_arg == ArgToInplace.RIGHT and isinstance(
|
147
170
|
self.left_arg, RegisterArithmeticInfo
|
148
171
|
):
|
@@ -173,28 +196,28 @@ class InplacableBinaryOpParams(
|
|
173
196
|
yield ArgToInplace.LEFT
|
174
197
|
|
175
198
|
def get_params_inplace_options(self) -> Iterable["InplacableBinaryOpParams"]:
|
176
|
-
params_kwargs = self.
|
199
|
+
params_kwargs = self.model_copy().__dict__
|
177
200
|
for inplace_arg in self._get_binary_op_inplace_options():
|
178
201
|
params_kwargs["inplace_arg"] = inplace_arg
|
179
202
|
yield self.__class__(**params_kwargs)
|
180
203
|
|
181
204
|
|
182
205
|
class BinaryOpWithIntInputs(BinaryOpParams[RegisterOrInt, RegisterOrInt]):
|
183
|
-
@pydantic.
|
184
|
-
def validate_int_registers(
|
185
|
-
left_arg =
|
206
|
+
@pydantic.model_validator(mode="after")
|
207
|
+
def validate_int_registers(self) -> Self:
|
208
|
+
left_arg = self.left_arg
|
186
209
|
is_left_arg_float_register = (
|
187
210
|
isinstance(left_arg, RegisterArithmeticInfo)
|
188
211
|
and left_arg.fraction_places > 0
|
189
212
|
)
|
190
|
-
right_arg =
|
213
|
+
right_arg = self.right_arg
|
191
214
|
is_right_arg_float_register = (
|
192
215
|
isinstance(right_arg, RegisterArithmeticInfo)
|
193
216
|
and right_arg.fraction_places > 0
|
194
217
|
)
|
195
218
|
if is_left_arg_float_register or is_right_arg_float_register:
|
196
|
-
raise
|
197
|
-
return
|
219
|
+
raise ClassiqValueError(BOOLEAN_OP_WITH_FRACTIONS_ERROR)
|
220
|
+
return self
|
198
221
|
|
199
222
|
@staticmethod
|
200
223
|
def _is_signed(arg: Union[int, RegisterArithmeticInfo]) -> bool:
|
@@ -245,74 +268,160 @@ class Adder(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
|
245
268
|
output_name = "sum"
|
246
269
|
|
247
270
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
248
|
-
|
249
|
-
self.
|
271
|
+
left_arg = argument_utils.limit_fraction_places(
|
272
|
+
self.left_arg, self.machine_precision
|
250
273
|
)
|
251
|
-
|
252
|
-
self.right_arg
|
274
|
+
right_arg = argument_utils.limit_fraction_places(
|
275
|
+
self.right_arg, self.machine_precision
|
276
|
+
)
|
277
|
+
lb = argument_utils.lower_bound(left_arg) + argument_utils.lower_bound(
|
278
|
+
right_arg
|
279
|
+
)
|
280
|
+
ub = argument_utils.upper_bound(left_arg) + argument_utils.upper_bound(
|
281
|
+
right_arg
|
253
282
|
)
|
254
|
-
integer_part_size = number_utils.bounds_to_integer_part_size(lb, ub)
|
255
283
|
fraction_places = max(
|
256
|
-
|
257
|
-
|
284
|
+
argument_utils.fraction_places(left_arg),
|
285
|
+
argument_utils.fraction_places(right_arg),
|
258
286
|
)
|
259
|
-
size_needed = integer_part_size + fraction_places
|
260
287
|
return RegisterArithmeticInfo(
|
261
|
-
size=self.output_size or
|
288
|
+
size=self.output_size or self._get_output_size(ub, lb, fraction_places),
|
262
289
|
fraction_places=fraction_places,
|
263
290
|
is_signed=self._include_sign and lb < 0,
|
264
291
|
bounds=(lb, ub) if self._include_sign else None,
|
265
292
|
)
|
266
293
|
|
294
|
+
def _get_output_size(self, ub: float, lb: float, fraction_places: int) -> int:
|
295
|
+
if isinstance(self.left_arg, float) and self.left_arg == 0.0:
|
296
|
+
if isinstance(self.right_arg, RegisterArithmeticInfo):
|
297
|
+
return self.right_arg.size
|
298
|
+
return as_arithmetic_info(self.right_arg).size
|
299
|
+
elif isinstance(self.right_arg, float) and self.right_arg == 0.0:
|
300
|
+
assert isinstance(self.left_arg, RegisterArithmeticInfo)
|
301
|
+
return self.left_arg.size
|
302
|
+
|
303
|
+
integer_part_size = number_utils.bounds_to_integer_part_size(lb, ub)
|
304
|
+
return integer_part_size + fraction_places
|
305
|
+
|
267
306
|
|
268
307
|
class Subtractor(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
269
308
|
output_name = "difference"
|
270
309
|
|
310
|
+
@staticmethod
|
311
|
+
def _get_effective_arg(
|
312
|
+
arg: RegisterOrConst, machine_precision: int
|
313
|
+
) -> RegisterOrConst:
|
314
|
+
return argument_utils.limit_fraction_places(arg, machine_precision)
|
315
|
+
|
316
|
+
@property
|
317
|
+
def effective_left_arg(self) -> RegisterOrConst:
|
318
|
+
return self._get_effective_arg(self.left_arg, self.machine_precision)
|
319
|
+
|
320
|
+
@property
|
321
|
+
def effective_right_arg(self) -> RegisterOrConst:
|
322
|
+
return self._get_effective_arg(self.right_arg, self.machine_precision)
|
323
|
+
|
324
|
+
@staticmethod
|
325
|
+
def _is_arg_trimmed_register(arg: RegisterOrConst, machine_precision: int) -> bool:
|
326
|
+
return (
|
327
|
+
isinstance(arg, RegisterArithmeticInfo)
|
328
|
+
and arg.fraction_places > machine_precision
|
329
|
+
)
|
330
|
+
|
331
|
+
@property
|
332
|
+
def left_arg_is_trimmed_register(self) -> bool:
|
333
|
+
return self._is_arg_trimmed_register(self.left_arg, self.machine_precision)
|
334
|
+
|
335
|
+
@property
|
336
|
+
def right_arg_is_trimmed_register(self) -> bool:
|
337
|
+
return self._is_arg_trimmed_register(self.right_arg, self.machine_precision)
|
338
|
+
|
271
339
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
272
340
|
bounds = (
|
273
|
-
argument_utils.lower_bound(self.
|
274
|
-
- argument_utils.upper_bound(self.
|
275
|
-
argument_utils.upper_bound(self.
|
276
|
-
- argument_utils.lower_bound(self.
|
341
|
+
argument_utils.lower_bound(self.effective_left_arg)
|
342
|
+
- argument_utils.upper_bound(self.effective_right_arg),
|
343
|
+
argument_utils.upper_bound(self.effective_left_arg)
|
344
|
+
- argument_utils.lower_bound(self.effective_right_arg),
|
277
345
|
)
|
278
|
-
integer_part_size = number_utils.bounds_to_integer_part_size(*bounds)
|
279
346
|
fraction_places = max(
|
280
|
-
|
281
|
-
|
347
|
+
argument_utils.fraction_places(self.effective_left_arg),
|
348
|
+
argument_utils.fraction_places(self.effective_right_arg),
|
282
349
|
)
|
283
|
-
|
350
|
+
|
351
|
+
size = self.output_size or self._get_output_size(bounds, fraction_places)
|
352
|
+
is_signed = self._include_sign and min(bounds) < 0
|
284
353
|
return RegisterArithmeticInfo(
|
285
|
-
size=
|
354
|
+
size=size,
|
286
355
|
fraction_places=fraction_places,
|
287
|
-
is_signed=
|
288
|
-
bounds=self._legal_bounds(
|
356
|
+
is_signed=is_signed,
|
357
|
+
bounds=self._legal_bounds(
|
358
|
+
bounds,
|
359
|
+
RegisterArithmeticInfo.get_maximal_bounds(
|
360
|
+
size=size, is_signed=is_signed, fraction_places=fraction_places
|
361
|
+
),
|
362
|
+
),
|
289
363
|
)
|
290
364
|
|
365
|
+
def _get_output_size(
|
366
|
+
self, bounds: tuple[float, float], fraction_places: int
|
367
|
+
) -> int:
|
368
|
+
if isinstance(self.right_arg, float) and self.effective_right_arg == 0:
|
369
|
+
assert isinstance(self.effective_left_arg, RegisterArithmeticInfo)
|
370
|
+
return self.effective_left_arg.size
|
371
|
+
integer_part_size = number_utils.bounds_to_integer_part_size(*bounds)
|
372
|
+
size_needed = integer_part_size + fraction_places
|
373
|
+
return size_needed
|
374
|
+
|
291
375
|
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
292
|
-
if
|
376
|
+
if (
|
377
|
+
not self.left_arg_is_trimmed_register
|
378
|
+
and not self.right_arg_is_trimmed_register
|
379
|
+
):
|
380
|
+
return self._untrimmed_garbage_output_size()
|
381
|
+
if not self.is_inplaced():
|
382
|
+
return 0
|
383
|
+
inplace_arg_name = (
|
384
|
+
self.left_arg_name
|
385
|
+
if self.inplace_arg == ArgToInplace.LEFT
|
386
|
+
else self.right_arg_name
|
387
|
+
)
|
388
|
+
return max(
|
389
|
+
0,
|
390
|
+
self._inputs[inplace_arg_name].fraction_places
|
391
|
+
- self.result_register.fraction_places,
|
392
|
+
)
|
393
|
+
|
394
|
+
def _untrimmed_garbage_output_size(self) -> pydantic.NonNegativeInt:
|
395
|
+
if not isinstance(self.effective_right_arg, RegisterArithmeticInfo):
|
293
396
|
adder_params = Adder(
|
294
|
-
left_arg=self.
|
295
|
-
right_arg=-self.
|
397
|
+
left_arg=self.effective_left_arg,
|
398
|
+
right_arg=-self.effective_right_arg,
|
296
399
|
output_size=self.output_size,
|
297
400
|
inplace_arg=self.inplace_arg,
|
298
401
|
)
|
299
402
|
return adder_params.garbage_output_size()
|
300
403
|
|
301
404
|
negation_params = Negation(
|
302
|
-
arg=self.
|
405
|
+
arg=self.effective_right_arg,
|
303
406
|
output_size=self.negation_output_size,
|
304
407
|
inplace=self.should_inplace_negation,
|
408
|
+
bypass_bounds_validation=True,
|
305
409
|
)
|
306
410
|
negation_result = negation_params.result_register
|
307
|
-
if self.output_size is None and max(self.
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
411
|
+
if self.output_size is None and max(self.effective_right_arg.bounds) > 0:
|
412
|
+
bounds = (
|
413
|
+
-max(self.effective_right_arg.bounds),
|
414
|
+
-min(self.effective_right_arg.bounds),
|
415
|
+
)
|
416
|
+
negation_result = RegisterArithmeticInfo(
|
417
|
+
size=negation_result.size,
|
418
|
+
fraction_places=negation_result.fraction_places,
|
419
|
+
is_signed=True,
|
420
|
+
bounds=bounds,
|
421
|
+
bypass_bounds_validation=True,
|
313
422
|
)
|
314
423
|
adder_params = Adder(
|
315
|
-
left_arg=self.
|
424
|
+
left_arg=self.effective_left_arg,
|
316
425
|
right_arg=negation_result,
|
317
426
|
output_size=self.output_size,
|
318
427
|
inplace_arg=self.arg_to_inplace_adder,
|
@@ -327,10 +436,10 @@ class Subtractor(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
|
327
436
|
return self.inplace_arg == ArgToInplace.LEFT
|
328
437
|
|
329
438
|
def _expected_negation_output_size(self) -> int:
|
330
|
-
return
|
439
|
+
return argument_utils.fraction_places(self.effective_right_arg) + min(
|
331
440
|
self.result_register.integer_part_size,
|
332
441
|
number_utils.bounds_to_integer_part_size(
|
333
|
-
*(-bound for bound in argument_utils.bounds(self.
|
442
|
+
*(-bound for bound in argument_utils.bounds(self.effective_right_arg))
|
334
443
|
),
|
335
444
|
)
|
336
445
|
|
@@ -356,29 +465,85 @@ class Subtractor(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
|
356
465
|
class Multiplier(BinaryOpWithFloatInputs):
|
357
466
|
output_name = "product"
|
358
467
|
|
359
|
-
def
|
360
|
-
|
361
|
-
self.left_arg
|
362
|
-
) +
|
468
|
+
def expected_fraction_places(self) -> int:
|
469
|
+
return argument_utils.fraction_places(
|
470
|
+
argument_utils.limit_fraction_places(self.left_arg, self.machine_precision)
|
471
|
+
) + argument_utils.fraction_places(
|
472
|
+
argument_utils.limit_fraction_places(self.right_arg, self.machine_precision)
|
473
|
+
)
|
474
|
+
|
475
|
+
@staticmethod
|
476
|
+
def _get_bounds(
|
477
|
+
args: tuple[RegisterOrConst, RegisterOrConst], machine_precision: int
|
478
|
+
) -> tuple[float, float]:
|
363
479
|
extremal_values = [
|
364
480
|
left * right
|
365
|
-
for left in argument_utils.bounds(
|
366
|
-
for right in argument_utils.bounds(
|
481
|
+
for left in argument_utils.bounds(args[0])
|
482
|
+
for right in argument_utils.bounds(args[1])
|
367
483
|
]
|
368
|
-
|
484
|
+
return (
|
485
|
+
number_utils.limit_fraction_places(min(extremal_values), machine_precision),
|
486
|
+
number_utils.limit_fraction_places(max(extremal_values), machine_precision),
|
487
|
+
)
|
488
|
+
|
489
|
+
def _get_result_register(self) -> RegisterArithmeticInfo:
|
490
|
+
fraction_places = min(self.machine_precision, self.expected_fraction_places())
|
491
|
+
left_arg = argument_utils.limit_fraction_places(
|
492
|
+
self.left_arg, self.machine_precision
|
493
|
+
)
|
494
|
+
right_arg = argument_utils.limit_fraction_places(
|
495
|
+
self.right_arg, self.machine_precision
|
496
|
+
)
|
497
|
+
bounds = self._get_bounds((left_arg, right_arg), self.machine_precision)
|
498
|
+
if self.output_size:
|
499
|
+
if fraction_places:
|
500
|
+
raise ValueError(MODULO_WITH_FRACTION_PLACES_ERROR_MSG)
|
501
|
+
max_bounds = RegisterArithmeticInfo.get_maximal_bounds(
|
502
|
+
size=self.output_size, is_signed=False, fraction_places=0
|
503
|
+
)
|
504
|
+
bounds = number_utils.bounds_cut(bounds, max_bounds)
|
505
|
+
|
506
|
+
size = self.output_size or self._get_output_size(
|
507
|
+
bounds, fraction_places, left_arg, right_arg
|
508
|
+
)
|
509
|
+
is_signed = self._include_sign and min(bounds) < 0
|
510
|
+
return RegisterArithmeticInfo(
|
511
|
+
size=size,
|
512
|
+
fraction_places=fraction_places,
|
513
|
+
is_signed=is_signed,
|
514
|
+
bounds=self._legal_bounds(
|
515
|
+
bounds,
|
516
|
+
RegisterArithmeticInfo.get_maximal_bounds(
|
517
|
+
size=size, is_signed=is_signed, fraction_places=fraction_places
|
518
|
+
),
|
519
|
+
),
|
520
|
+
)
|
521
|
+
|
522
|
+
@staticmethod
|
523
|
+
def _get_output_size(
|
524
|
+
bounds: tuple[float, float],
|
525
|
+
fraction_places: int,
|
526
|
+
left_arg: Union[RegisterArithmeticInfo, float],
|
527
|
+
right_arg: Union[RegisterArithmeticInfo, float],
|
528
|
+
) -> int:
|
529
|
+
if isinstance(left_arg, float) and left_arg == 1.0:
|
530
|
+
assert isinstance(right_arg, RegisterArithmeticInfo)
|
531
|
+
return right_arg.size
|
532
|
+
elif isinstance(right_arg, float) and right_arg == 1.0:
|
533
|
+
assert isinstance(left_arg, RegisterArithmeticInfo)
|
534
|
+
return left_arg.size
|
369
535
|
largest_bound = max(bounds, key=abs)
|
370
536
|
integer_places = int(largest_bound).bit_length() + int(largest_bound < 0)
|
371
537
|
extra_sign_bit = int(
|
372
|
-
argument_utils.is_signed(
|
373
|
-
and argument_utils.is_signed(
|
538
|
+
argument_utils.is_signed(left_arg)
|
539
|
+
and argument_utils.is_signed(right_arg)
|
374
540
|
and largest_bound > 0
|
375
541
|
)
|
376
|
-
return
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
bounds=self._legal_bounds(bounds),
|
542
|
+
return max(1, integer_places + fraction_places + extra_sign_bit)
|
543
|
+
|
544
|
+
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
545
|
+
return max(
|
546
|
+
0, self.expected_fraction_places() - self.result_register.fraction_places
|
382
547
|
)
|
383
548
|
|
384
549
|
|
@@ -416,29 +581,57 @@ class LessEqual(Comparator):
|
|
416
581
|
class Power(BinaryOpParams[RegisterArithmeticInfo, pydantic.PositiveInt]):
|
417
582
|
output_name = "powered"
|
418
583
|
|
419
|
-
@pydantic.
|
584
|
+
@pydantic.field_validator("right_arg", mode="before")
|
585
|
+
@classmethod
|
420
586
|
def _validate_legal_power(cls, right_arg: Any) -> pydantic.PositiveInt:
|
421
587
|
if not float(right_arg).is_integer():
|
422
|
-
raise
|
588
|
+
raise ClassiqValueError("Power must be an integer")
|
423
589
|
if right_arg <= 0:
|
424
|
-
raise
|
590
|
+
raise ClassiqValueError("Power must be greater than one")
|
425
591
|
return int(right_arg)
|
426
592
|
|
427
|
-
def
|
428
|
-
|
593
|
+
def expected_fraction_places(self) -> int:
|
594
|
+
return (
|
595
|
+
argument_utils.fraction_places(
|
596
|
+
argument_utils.limit_fraction_places(
|
597
|
+
self.left_arg, self.machine_precision
|
598
|
+
)
|
599
|
+
)
|
600
|
+
* self.right_arg
|
601
|
+
)
|
602
|
+
|
603
|
+
def _get_result_bounds(self) -> tuple[float, float]:
|
604
|
+
bounds = [
|
605
|
+
number_utils.limit_fraction_places(
|
606
|
+
bound, machine_precision=self.machine_precision
|
607
|
+
)
|
608
|
+
for bound in self.left_arg.bounds
|
609
|
+
]
|
610
|
+
if (self.right_arg % 2) or min(bounds) >= 0:
|
429
611
|
return (
|
430
|
-
|
431
|
-
|
612
|
+
number_utils.limit_fraction_places(
|
613
|
+
bounds[0] ** self.right_arg,
|
614
|
+
machine_precision=self.machine_precision,
|
615
|
+
),
|
616
|
+
number_utils.limit_fraction_places(
|
617
|
+
bounds[1] ** self.right_arg,
|
618
|
+
machine_precision=self.machine_precision,
|
619
|
+
),
|
432
620
|
)
|
433
|
-
return 0.0,
|
621
|
+
return 0.0, number_utils.limit_fraction_places(
|
622
|
+
max(abs(bound) for bound in bounds) ** self.right_arg,
|
623
|
+
machine_precision=self.machine_precision,
|
624
|
+
)
|
434
625
|
|
435
626
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
436
627
|
if self.output_size:
|
437
628
|
return RegisterArithmeticInfo(size=self.output_size)
|
438
629
|
|
439
|
-
fraction_places
|
630
|
+
fraction_places = min(self.machine_precision, self.expected_fraction_places())
|
440
631
|
bounds = self._get_result_bounds()
|
441
632
|
size = number_utils.bounds_to_integer_part_size(*bounds) + fraction_places
|
633
|
+
if bounds[0] == bounds[1]:
|
634
|
+
size = 1
|
442
635
|
return RegisterArithmeticInfo(
|
443
636
|
size=size,
|
444
637
|
is_signed=self.left_arg.is_signed and (self.right_arg % 2 == 1),
|
@@ -446,6 +639,50 @@ class Power(BinaryOpParams[RegisterArithmeticInfo, pydantic.PositiveInt]):
|
|
446
639
|
bounds=bounds,
|
447
640
|
)
|
448
641
|
|
642
|
+
def _get_inner_action_garbage_size(
|
643
|
+
self,
|
644
|
+
action_type: Union[type["Power"], type[Multiplier]],
|
645
|
+
*,
|
646
|
+
arg: RegisterArithmeticInfo,
|
647
|
+
action_right_arg: RegisterOrConst,
|
648
|
+
compute_power: int,
|
649
|
+
) -> pydantic.NonNegativeInt:
|
650
|
+
inner_compute_power_params = Power(
|
651
|
+
left_arg=arg,
|
652
|
+
right_arg=compute_power,
|
653
|
+
output_size=self.output_size,
|
654
|
+
machine_precision=self.machine_precision,
|
655
|
+
)
|
656
|
+
return action_type(
|
657
|
+
left_arg=inner_compute_power_params.result_register,
|
658
|
+
right_arg=action_right_arg,
|
659
|
+
output_size=self.output_size,
|
660
|
+
machine_precision=self.machine_precision,
|
661
|
+
).garbage_output_size()
|
662
|
+
|
663
|
+
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
664
|
+
arg = self.left_arg
|
665
|
+
power = self.right_arg
|
666
|
+
if power == 1:
|
667
|
+
return 0
|
668
|
+
if (
|
669
|
+
power == 2
|
670
|
+
or (arg.size == 1 and arg.fraction_places == 0)
|
671
|
+
or self.output_size == 1
|
672
|
+
):
|
673
|
+
return max(
|
674
|
+
0,
|
675
|
+
self.expected_fraction_places() - self.result_register.fraction_places,
|
676
|
+
)
|
677
|
+
|
678
|
+
if power % 2 == 0:
|
679
|
+
return self._get_inner_action_garbage_size(
|
680
|
+
Power, arg=arg, action_right_arg=power // 2, compute_power=2
|
681
|
+
)
|
682
|
+
return self._get_inner_action_garbage_size(
|
683
|
+
Multiplier, arg=arg, action_right_arg=arg, compute_power=power - 1
|
684
|
+
)
|
685
|
+
|
449
686
|
|
450
687
|
class EffectiveUnaryOpParams(
|
451
688
|
InplacableBinaryOpParams[RegisterArithmeticInfo, RightDataT], Generic[RightDataT]
|
@@ -457,19 +694,19 @@ class LShift(EffectiveUnaryOpParams[pydantic.NonNegativeInt]):
|
|
457
694
|
output_name = "left_shifted"
|
458
695
|
inplace_arg: Optional[ArgToInplace] = ArgToInplace.LEFT
|
459
696
|
|
460
|
-
@pydantic.
|
461
|
-
def _validate_legal_modulo(
|
462
|
-
output_size =
|
697
|
+
@pydantic.model_validator(mode="after")
|
698
|
+
def _validate_legal_modulo(self) -> Self:
|
699
|
+
output_size = self.output_size
|
463
700
|
if output_size is None:
|
464
|
-
return
|
465
|
-
arg =
|
466
|
-
shift =
|
701
|
+
return self
|
702
|
+
arg = self.left_arg
|
703
|
+
shift = self.right_arg
|
467
704
|
if not isinstance(arg, RegisterArithmeticInfo):
|
468
|
-
raise
|
705
|
+
raise ClassiqValueError("left arg must be a RegisterArithmeticInfo")
|
469
706
|
if not isinstance(shift, int):
|
470
|
-
raise
|
707
|
+
raise ClassiqValueError("Shift must be an integer")
|
471
708
|
assert arg.fraction_places - shift <= 0, _FLOATING_POINT_MODULO_ERROR_MESSAGE
|
472
|
-
return
|
709
|
+
return self
|
473
710
|
|
474
711
|
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
475
712
|
if self.inplace_arg is None or self.output_size is None:
|
@@ -498,21 +735,21 @@ class RShift(EffectiveUnaryOpParams[pydantic.NonNegativeInt]):
|
|
498
735
|
def _shifted_fraction_places(*, arg: RegisterArithmeticInfo, shift: int) -> int:
|
499
736
|
return arg.fraction_places * int(arg.is_signed or shift < arg.size)
|
500
737
|
|
501
|
-
@pydantic.
|
502
|
-
def _validate_legal_modulo(
|
503
|
-
output_size =
|
738
|
+
@pydantic.model_validator(mode="after")
|
739
|
+
def _validate_legal_modulo(self) -> Self:
|
740
|
+
output_size = self.output_size
|
504
741
|
if output_size is None:
|
505
|
-
return
|
506
|
-
arg =
|
507
|
-
shift =
|
742
|
+
return self
|
743
|
+
arg = self.left_arg
|
744
|
+
shift = self.right_arg
|
508
745
|
if not isinstance(arg, RegisterArithmeticInfo):
|
509
|
-
raise
|
746
|
+
raise ClassiqValueError("left arg must be a RegisterArithmeticInfo")
|
510
747
|
if not isinstance(shift, int):
|
511
|
-
raise
|
748
|
+
raise ClassiqValueError("Shift must be an integer")
|
512
749
|
assert (
|
513
|
-
|
750
|
+
self._shifted_fraction_places(arg=arg, shift=shift) == 0
|
514
751
|
), _FLOATING_POINT_MODULO_ERROR_MESSAGE
|
515
|
-
return
|
752
|
+
return self
|
516
753
|
|
517
754
|
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
518
755
|
if self.inplace_arg is None:
|
@@ -542,16 +779,16 @@ class CyclicShift(EffectiveUnaryOpParams[int]):
|
|
542
779
|
output_name = "cyclic_shifted"
|
543
780
|
inplace_arg: Optional[ArgToInplace] = ArgToInplace.LEFT
|
544
781
|
|
545
|
-
@pydantic.
|
546
|
-
def _validate_legal_modulo(
|
547
|
-
output_size =
|
782
|
+
@pydantic.model_validator(mode="after")
|
783
|
+
def _validate_legal_modulo(self) -> Self:
|
784
|
+
output_size = self.output_size
|
548
785
|
if output_size is None:
|
549
|
-
return
|
550
|
-
arg =
|
786
|
+
return self
|
787
|
+
arg = self.left_arg
|
551
788
|
if not isinstance(arg, RegisterArithmeticInfo):
|
552
|
-
raise
|
789
|
+
raise ClassiqValueError("left arg must be a RegisterArithmeticInfo")
|
553
790
|
assert arg.fraction_places == 0, _FLOATING_POINT_MODULO_ERROR_MESSAGE
|
554
|
-
return
|
791
|
+
return self
|
555
792
|
|
556
793
|
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
557
794
|
if self.inplace_arg is None:
|
@@ -570,31 +807,30 @@ class Modulo(EffectiveUnaryOpParams[int]):
|
|
570
807
|
output_name = "modulus"
|
571
808
|
inplace_arg: Optional[ArgToInplace] = ArgToInplace.LEFT
|
572
809
|
|
573
|
-
@pydantic.
|
810
|
+
@pydantic.field_validator("left_arg", mode="before")
|
811
|
+
@classmethod
|
574
812
|
def _validate_left_arg_is_integer(
|
575
813
|
cls, left_arg: RegisterArithmeticInfo
|
576
814
|
) -> RegisterArithmeticInfo:
|
577
815
|
assert left_arg.fraction_places == 0, _FLOATING_POINT_MODULO_ERROR_MESSAGE
|
578
816
|
return left_arg
|
579
817
|
|
580
|
-
@pydantic.
|
818
|
+
@pydantic.field_validator("right_arg", mode="before")
|
819
|
+
@classmethod
|
581
820
|
def _validate_right_arg_is_a_power_of_two(
|
582
|
-
cls, right_arg: int,
|
821
|
+
cls, right_arg: int, info: ValidationInfo
|
583
822
|
) -> int:
|
584
823
|
repr_qubits_float = math.log2(right_arg)
|
585
824
|
repr_qubits = round(repr_qubits_float)
|
586
825
|
assert abs(repr_qubits - repr_qubits_float) < 10**-8, NOT_POWER_OF_TWO_ERROR_MSG
|
587
|
-
output_size =
|
826
|
+
output_size = info.data.get("output_size")
|
588
827
|
if output_size is not None:
|
589
828
|
repr_qubits = min(repr_qubits, output_size)
|
590
|
-
|
829
|
+
info.data["output_size"] = None
|
591
830
|
return 2 ** (repr_qubits)
|
592
831
|
|
593
|
-
@property
|
594
|
-
def result_size(self) -> int:
|
595
|
-
return round(math.log2(self.right_arg))
|
596
|
-
|
597
832
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
598
|
-
|
599
|
-
|
600
|
-
|
833
|
+
size = round(math.log2(self.right_arg))
|
834
|
+
if size <= 0:
|
835
|
+
raise ClassiqValueError("Cannot use a quantum expression with zero size")
|
836
|
+
return RegisterArithmeticInfo(size=size, is_signed=False, fraction_places=0)
|