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,12 +1,14 @@
|
|
1
1
|
import abc
|
2
2
|
import ast
|
3
3
|
import re
|
4
|
-
from typing import Any,
|
4
|
+
from typing import Any, Optional, Union
|
5
5
|
|
6
6
|
import networkx as nx
|
7
7
|
import pydantic
|
8
|
+
from pydantic import TypeAdapter
|
8
9
|
from typing_extensions import TypeAlias
|
9
10
|
|
11
|
+
from classiq.interface.exceptions import ClassiqValueError
|
10
12
|
from classiq.interface.generator.arith import number_utils
|
11
13
|
from classiq.interface.generator.arith.arithmetic_expression_parser import (
|
12
14
|
parse_expression,
|
@@ -17,6 +19,9 @@ from classiq.interface.generator.arith.arithmetic_expression_validator import (
|
|
17
19
|
from classiq.interface.generator.arith.arithmetic_result_builder import (
|
18
20
|
validate_arithmetic_result_type,
|
19
21
|
)
|
22
|
+
from classiq.interface.generator.arith.machine_precision import (
|
23
|
+
DEFAULT_MACHINE_PRECISION,
|
24
|
+
)
|
20
25
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
21
26
|
from classiq.interface.generator.arith.uncomputation_methods import UncomputationMethods
|
22
27
|
from classiq.interface.generator.expressions.expression_constants import (
|
@@ -27,8 +32,6 @@ from classiq.interface.generator.expressions.expression_constants import (
|
|
27
32
|
from classiq.interface.generator.function_params import FunctionParams
|
28
33
|
from classiq.interface.helpers.custom_pydantic_types import PydanticExpressionStr
|
29
34
|
|
30
|
-
from classiq.exceptions import ClassiqValueError
|
31
|
-
|
32
35
|
ValidDefinitions: TypeAlias = Union[
|
33
36
|
pydantic.StrictInt, pydantic.StrictFloat, RegisterArithmeticInfo
|
34
37
|
]
|
@@ -36,22 +39,18 @@ ValidDefinitions: TypeAlias = Union[
|
|
36
39
|
|
37
40
|
class ArithmeticExpressionABC(abc.ABC, FunctionParams):
|
38
41
|
uncomputation_method: UncomputationMethods = UncomputationMethods.optimized
|
39
|
-
machine_precision: pydantic.NonNegativeInt =
|
42
|
+
machine_precision: pydantic.NonNegativeInt = DEFAULT_MACHINE_PRECISION
|
40
43
|
expression: PydanticExpressionStr
|
41
|
-
definitions:
|
44
|
+
definitions: dict[str, ValidDefinitions]
|
42
45
|
qubit_count: Optional[pydantic.NonNegativeInt] = None
|
43
46
|
|
44
|
-
def _get_literal_set(self) ->
|
47
|
+
def _get_literal_set(self) -> set[str]:
|
45
48
|
return _extract_literals(self.expression)
|
46
49
|
|
47
|
-
@
|
50
|
+
@classmethod
|
48
51
|
def _validate_expression_literals_and_definitions(
|
49
|
-
cls, definitions:
|
50
|
-
) ->
|
51
|
-
expression = values.get("expression")
|
52
|
-
if expression is None:
|
53
|
-
return definitions
|
54
|
-
|
52
|
+
cls, definitions: dict[str, ValidDefinitions], expression: PydanticExpressionStr
|
53
|
+
) -> dict[str, ValidDefinitions]:
|
55
54
|
literals = _extract_literals(expression)
|
56
55
|
|
57
56
|
forbidden = literals.intersection(FORBIDDEN_LITERALS)
|
@@ -68,12 +67,33 @@ class ArithmeticExpressionABC(abc.ABC, FunctionParams):
|
|
68
67
|
raise ClassiqValueError(f"The following names are undefined: {undefined}")
|
69
68
|
return definitions
|
70
69
|
|
71
|
-
@pydantic.
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
@pydantic.model_validator(mode="before")
|
71
|
+
@classmethod
|
72
|
+
def _validate_expression(cls, values: Any) -> dict[str, Any]:
|
73
|
+
if not isinstance(values, dict):
|
74
|
+
return values
|
75
|
+
expression_adapter: TypeAdapter = TypeAdapter(Optional[PydanticExpressionStr])
|
76
|
+
expression = expression_adapter.validate_python(values.get("expression"))
|
77
|
+
definitions_adapter: TypeAdapter = TypeAdapter(
|
78
|
+
Optional[dict[str, ValidDefinitions]]
|
79
|
+
)
|
80
|
+
definition_dict = values.get("definitions")
|
81
|
+
if (
|
82
|
+
isinstance(definition_dict, list)
|
83
|
+
and len(definition_dict) > 0
|
84
|
+
and isinstance(definition_dict[0], tuple)
|
85
|
+
):
|
86
|
+
definition_dict = dict(definition_dict)
|
87
|
+
definitions = definitions_adapter.validate_python(definition_dict)
|
88
|
+
machine_precision: Optional[int] = values.get(
|
89
|
+
"machine_precision", DEFAULT_MACHINE_PRECISION
|
90
|
+
)
|
91
|
+
if (
|
92
|
+
expression is None
|
93
|
+
or expression == ""
|
94
|
+
or definitions is None
|
95
|
+
or machine_precision is None
|
96
|
+
):
|
77
97
|
return values
|
78
98
|
|
79
99
|
try:
|
@@ -85,15 +105,39 @@ class ArithmeticExpressionABC(abc.ABC, FunctionParams):
|
|
85
105
|
cls._validate_ast_obj(ast_obj)
|
86
106
|
|
87
107
|
graph = parse_expression(expression)
|
88
|
-
|
108
|
+
try:
|
109
|
+
cls._validate_expression_graph(graph, values)
|
110
|
+
except ClassiqValueError as e:
|
111
|
+
# This flow was created specifically for inplace Boolean XOR operations like q1 ^ q2.
|
112
|
+
# We can't plug equality in previous stages due to SymPy restrictions.
|
113
|
+
# Note that we don't validate that the expression itself is Boolean (passing non-Boolean expressions
|
114
|
+
# as inplace is currently not supported, so it's a bug).
|
115
|
+
if not e.raw_message == "Expression does not support target assignment":
|
116
|
+
raise
|
117
|
+
ast_parsed_expression = ast.parse(expression)
|
118
|
+
ast_expr = ast_parsed_expression.body[0]
|
119
|
+
if (
|
120
|
+
not isinstance(ast_expr, ast.Expr)
|
121
|
+
or not isinstance(ast_expr.value, ast.BinOp)
|
122
|
+
or not isinstance(ast_expr.value.op, ast.BitXor)
|
123
|
+
):
|
124
|
+
raise
|
125
|
+
expression = f"({expression}) == 1"
|
126
|
+
graph = parse_expression(expression)
|
127
|
+
cls._validate_expression_graph(graph, values)
|
128
|
+
|
129
|
+
validated_defs = cls._validate_expression_literals_and_definitions(
|
130
|
+
definitions, expression
|
131
|
+
)
|
132
|
+
|
89
133
|
validate_arithmetic_result_type(
|
90
134
|
graph=graph,
|
91
|
-
definitions=
|
135
|
+
definitions=validated_defs,
|
92
136
|
machine_precision=machine_precision,
|
93
137
|
)
|
94
138
|
|
95
139
|
new_expr, new_defs = cls._replace_const_definitions_in_expression(
|
96
|
-
expression,
|
140
|
+
expression, validated_defs, machine_precision
|
97
141
|
)
|
98
142
|
values["expression"] = new_expr
|
99
143
|
values["definitions"] = new_defs
|
@@ -104,16 +148,16 @@ class ArithmeticExpressionABC(abc.ABC, FunctionParams):
|
|
104
148
|
pass
|
105
149
|
|
106
150
|
@staticmethod
|
107
|
-
def _validate_expression_graph(graph: nx.DiGraph, values:
|
151
|
+
def _validate_expression_graph(graph: nx.DiGraph, values: dict[str, Any]) -> None:
|
108
152
|
pass
|
109
153
|
|
110
154
|
@classmethod
|
111
155
|
def _replace_const_definitions_in_expression(
|
112
156
|
cls,
|
113
157
|
expression: str,
|
114
|
-
definitions:
|
158
|
+
definitions: dict[str, ValidDefinitions],
|
115
159
|
machine_precision: int,
|
116
|
-
) ->
|
160
|
+
) -> tuple[str, dict[str, RegisterArithmeticInfo]]:
|
117
161
|
new_definitions = dict()
|
118
162
|
for var_name, value in definitions.items():
|
119
163
|
if isinstance(value, RegisterArithmeticInfo):
|
@@ -138,5 +182,5 @@ class ArithmeticExpressionABC(abc.ABC, FunctionParams):
|
|
138
182
|
return re.sub(r"\b" + var + r"\b", str(value), expression)
|
139
183
|
|
140
184
|
|
141
|
-
def _extract_literals(expression: str) ->
|
185
|
+
def _extract_literals(expression: str) -> set[str]:
|
142
186
|
return set(re.findall(SUPPORTED_VAR_NAMES_REG, expression)) - SUPPORTED_FUNC_NAMES
|
@@ -1,9 +1,11 @@
|
|
1
1
|
import ast
|
2
2
|
from _ast import AST
|
3
|
-
from
|
3
|
+
from collections.abc import Collection
|
4
|
+
from typing import Optional, Union, cast
|
4
5
|
|
5
6
|
import networkx as nx
|
6
7
|
|
8
|
+
from classiq.interface.exceptions import ClassiqArithmeticError
|
7
9
|
from classiq.interface.generator.arith.arithmetic_expression_validator import (
|
8
10
|
DEFAULT_EXPRESSION_TYPE,
|
9
11
|
DEFAULT_SUPPORTED_FUNC_NAMES,
|
@@ -16,10 +18,10 @@ from classiq.interface.generator.arith.ast_node_rewrite import (
|
|
16
18
|
AstNodeRewrite,
|
17
19
|
)
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
_MULTIPLE_RESULTS_ERROR_MESSAGE: str = "Expression cannot contain multiple results"
|
22
|
+
_UNEXPECTED_ARITHMETIC_ERROR_MESSAGE: str = (
|
23
|
+
"Quantum expressions that evaluate to a classical value are not supported"
|
24
|
+
)
|
23
25
|
_ALLOWED_MULTI_ARGUMENT_FUNCTIONS = ("min", "max")
|
24
26
|
Node = Union[str, float, int]
|
25
27
|
|
@@ -27,13 +29,17 @@ Node = Union[str, float, int]
|
|
27
29
|
class ExpressionVisitor(ExpressionValidator):
|
28
30
|
def __init__(
|
29
31
|
self,
|
30
|
-
supported_nodes:
|
32
|
+
supported_nodes: tuple[type[AST], ...],
|
31
33
|
expression_type: str = DEFAULT_EXPRESSION_TYPE,
|
32
|
-
supported_functions: Optional[
|
34
|
+
supported_functions: Optional[set[str]] = None,
|
33
35
|
) -> None:
|
34
36
|
super().__init__(supported_nodes, expression_type, supported_functions)
|
35
37
|
self.graph = nx.DiGraph()
|
36
38
|
|
39
|
+
@classmethod
|
40
|
+
def rewrite_ast(cls, expression_ast: AST) -> AST:
|
41
|
+
return AstNodeRewrite().visit(expression_ast)
|
42
|
+
|
37
43
|
def visit_Compare(self, node: ast.Compare) -> None:
|
38
44
|
self.validate_Compare(node)
|
39
45
|
self.update_graph(node, node.left, node.comparators[0])
|
@@ -85,8 +91,8 @@ class ExpressionVisitor(ExpressionValidator):
|
|
85
91
|
class InDegreeLimiter:
|
86
92
|
@staticmethod
|
87
93
|
def _sort_in_edges(
|
88
|
-
in_edges: Collection[
|
89
|
-
) ->
|
94
|
+
in_edges: Collection[tuple[Node, str]]
|
95
|
+
) -> list[tuple[Node, str]]:
|
90
96
|
return sorted(
|
91
97
|
in_edges,
|
92
98
|
key=lambda edge_tuple: isinstance(edge_tuple[0], str), # vars before consts
|
@@ -122,16 +128,16 @@ class InDegreeLimiter:
|
|
122
128
|
if num_results > 1:
|
123
129
|
raise ClassiqArithmeticError(_MULTIPLE_RESULTS_ERROR_MESSAGE)
|
124
130
|
elif num_results == 0:
|
125
|
-
raise ClassiqArithmeticError(
|
131
|
+
raise ClassiqArithmeticError(_UNEXPECTED_ARITHMETIC_ERROR_MESSAGE)
|
126
132
|
return graph
|
127
133
|
|
128
134
|
|
129
135
|
def parse_expression(
|
130
136
|
expression: str,
|
131
137
|
*,
|
132
|
-
supported_nodes:
|
138
|
+
supported_nodes: tuple[type[AST], ...] = DEFAULT_SUPPORTED_NODE_TYPES,
|
133
139
|
expression_type: str = DEFAULT_EXPRESSION_TYPE,
|
134
|
-
supported_functions: Optional[
|
140
|
+
supported_functions: Optional[set[str]] = None,
|
135
141
|
) -> nx.DiGraph:
|
136
142
|
supported_functions = supported_functions or DEFAULT_SUPPORTED_FUNC_NAMES
|
137
143
|
|
@@ -1,24 +1,23 @@
|
|
1
1
|
import ast
|
2
|
-
import
|
2
|
+
import re
|
3
3
|
from _ast import AST
|
4
|
-
from typing import Any, Optional,
|
4
|
+
from typing import Any, Optional, Union
|
5
5
|
|
6
|
-
from
|
6
|
+
from sympy import Expr
|
7
|
+
from typing_extensions import TypeAlias, get_args
|
7
8
|
|
9
|
+
from classiq.interface.exceptions import ClassiqArithmeticError, ClassiqValueError
|
8
10
|
from classiq.interface.generator.arith.ast_node_rewrite import AstNodeRewrite
|
9
11
|
from classiq.interface.generator.expressions.sympy_supported_expressions import (
|
10
12
|
SYMPY_SUPPORTED_EXPRESSIONS,
|
11
13
|
)
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
DEFAULT_SUPPORTED_FUNC_NAMES: Set[str] = {"CLShift", "CRShift", "min", "max"}
|
15
|
+
DEFAULT_SUPPORTED_FUNC_NAMES: set[str] = {"CLShift", "CRShift", "min", "max"}
|
16
16
|
|
17
17
|
DEFAULT_EXPRESSION_TYPE = "arithmetic"
|
18
|
+
IDENITIFIER_REGEX = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*")
|
18
19
|
|
19
|
-
|
20
|
-
"Repeated variables in the beginning of an arithmetic expression are not allowed."
|
21
|
-
)
|
20
|
+
ValidKeyValuePairs: TypeAlias = dict[str, set[str]]
|
22
21
|
|
23
22
|
SupportedNodesTypes = Union[
|
24
23
|
ast.Expression,
|
@@ -56,49 +55,75 @@ SupportedNodesTypes = Union[
|
|
56
55
|
DEFAULT_SUPPORTED_NODE_TYPES = get_args(SupportedNodesTypes)
|
57
56
|
|
58
57
|
|
58
|
+
def is_constant(expr: Union[str, Expr]) -> bool:
|
59
|
+
try:
|
60
|
+
float(expr)
|
61
|
+
return True
|
62
|
+
except (ValueError, TypeError):
|
63
|
+
return False
|
64
|
+
|
65
|
+
|
59
66
|
class ExpressionValidator(ast.NodeVisitor):
|
60
67
|
def __init__(
|
61
68
|
self,
|
62
|
-
supported_nodes:
|
69
|
+
supported_nodes: tuple[type[AST], ...],
|
63
70
|
expression_type: str = DEFAULT_EXPRESSION_TYPE,
|
64
|
-
supported_functions: Optional[
|
65
|
-
supported_attr_values: Optional[Set[str]] = None,
|
71
|
+
supported_functions: Optional[set[str]] = None,
|
66
72
|
mode: str = "eval",
|
67
73
|
) -> None:
|
68
74
|
super().__init__()
|
69
75
|
self.supported_nodes = supported_nodes
|
70
76
|
self._expression_type = expression_type
|
71
77
|
self._supported_functions = supported_functions or DEFAULT_SUPPORTED_FUNC_NAMES
|
72
|
-
self._supported_attr_values = supported_attr_values or set()
|
73
78
|
self._mode = mode
|
74
79
|
self._ast_obj: Optional[ast.AST] = None
|
75
80
|
|
76
81
|
def validate(self, expression: str) -> None:
|
77
82
|
try:
|
78
|
-
|
83
|
+
adjusted_expression = self._get_adjusted_expression(expression)
|
84
|
+
ast_expr = ast.parse(adjusted_expression, filename="", mode=self._mode)
|
79
85
|
except SyntaxError as e:
|
80
86
|
raise ClassiqValueError(f"Failed to parse expression {expression!r}") from e
|
81
87
|
try:
|
82
|
-
self._ast_obj =
|
88
|
+
self._ast_obj = self.rewrite_ast(ast_expr)
|
83
89
|
self.visit(self._ast_obj)
|
84
90
|
except RecursionError as e:
|
85
91
|
raise ClassiqValueError(
|
86
92
|
f"Failed to parse expression since it is too long: {expression}"
|
87
93
|
) from e
|
88
94
|
|
95
|
+
@staticmethod
|
96
|
+
def _get_adjusted_expression(expression: str) -> str:
|
97
|
+
# This works around the simplification of the trivial expressions such as a + 0, 1 * a, etc.
|
98
|
+
if IDENITIFIER_REGEX.fullmatch(expression) or is_constant(expression):
|
99
|
+
return f"0 + {expression}"
|
100
|
+
return expression
|
101
|
+
|
89
102
|
@property
|
90
103
|
def ast_obj(self) -> ast.AST:
|
91
104
|
if not self._ast_obj:
|
92
105
|
raise ClassiqArithmeticError("Must call `validate` before getting ast_obj")
|
93
106
|
return self._ast_obj
|
94
107
|
|
95
|
-
|
96
|
-
|
108
|
+
def _check_repeated_variables(
|
109
|
+
self, variables: tuple[Any, Any], expr: ast.AST, error_suffix: str
|
110
|
+
) -> None:
|
111
|
+
if (
|
112
|
+
isinstance(expr, ast.BinOp)
|
113
|
+
and isinstance(expr.op, ast.Pow)
|
114
|
+
and ast.Pow not in self.supported_nodes
|
115
|
+
):
|
116
|
+
raise ClassiqValueError(
|
117
|
+
"Raising to a power (<var> ** <exp>) and multiplying a variable by "
|
118
|
+
"itself (<var> * <var>) are not supported"
|
119
|
+
)
|
97
120
|
if (
|
98
121
|
all(isinstance(var, ast.Name) for var in variables)
|
99
122
|
and variables[0].id == variables[1].id
|
100
123
|
):
|
101
|
-
raise ClassiqValueError(
|
124
|
+
raise ClassiqValueError(
|
125
|
+
f"Expression {ast.unparse(expr)!r} is not supported ({error_suffix})"
|
126
|
+
)
|
102
127
|
|
103
128
|
@staticmethod
|
104
129
|
def _check_multiple_comparators(node: ast.Compare) -> None:
|
@@ -120,7 +145,11 @@ class ExpressionValidator(ast.NodeVisitor):
|
|
120
145
|
)
|
121
146
|
|
122
147
|
def validate_Compare(self, node: ast.Compare) -> None: # noqa: N802
|
123
|
-
self._check_repeated_variables(
|
148
|
+
self._check_repeated_variables(
|
149
|
+
(node.left, node.comparators[0]),
|
150
|
+
node,
|
151
|
+
"both sides of the comparison are identical",
|
152
|
+
)
|
124
153
|
self._check_multiple_comparators(node)
|
125
154
|
|
126
155
|
def visit_Compare(self, node: ast.Compare) -> None:
|
@@ -128,7 +157,9 @@ class ExpressionValidator(ast.NodeVisitor):
|
|
128
157
|
self.generic_visit(node)
|
129
158
|
|
130
159
|
def validate_BinOp(self, node: ast.BinOp) -> None: # noqa: N802
|
131
|
-
self._check_repeated_variables(
|
160
|
+
self._check_repeated_variables(
|
161
|
+
(node.left, node.right), node, "both sides of the operation are identical"
|
162
|
+
)
|
132
163
|
|
133
164
|
def visit_BinOp(self, node: ast.BinOp) -> None:
|
134
165
|
self.validate_BinOp(node)
|
@@ -136,7 +167,11 @@ class ExpressionValidator(ast.NodeVisitor):
|
|
136
167
|
|
137
168
|
def validate_Call(self, node: ast.Call) -> None: # noqa: N802
|
138
169
|
if len(node.args) >= 2:
|
139
|
-
self._check_repeated_variables(
|
170
|
+
self._check_repeated_variables(
|
171
|
+
(node.args[0], node.args[1]),
|
172
|
+
node,
|
173
|
+
"the first two call arguments are identical",
|
174
|
+
)
|
140
175
|
node_id = AstNodeRewrite().extract_node_id(node)
|
141
176
|
if node_id not in self._supported_functions:
|
142
177
|
raise ClassiqValueError(f"{node_id} not in supported functions")
|
@@ -160,36 +195,20 @@ class ExpressionValidator(ast.NodeVisitor):
|
|
160
195
|
self.validate_Constant(node)
|
161
196
|
self.generic_visit(node)
|
162
197
|
|
163
|
-
def validate_Attribute(self, node: ast.Attribute) -> None: # noqa: N802
|
164
|
-
if not (
|
165
|
-
isinstance(node.value, ast.Name)
|
166
|
-
and node.value.id in self._supported_attr_values
|
167
|
-
):
|
168
|
-
raise ClassiqValueError(
|
169
|
-
f"Attribute is not supported for value {node.value}"
|
170
|
-
)
|
171
|
-
|
172
198
|
def visit_Attribute(self, node: ast.Attribute) -> None:
|
173
|
-
self.validate_Attribute(node)
|
174
199
|
self.generic_visit(node)
|
175
200
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
raise ClassiqValueError(
|
180
|
-
f"Defining a function named {node.name} is forbidden"
|
181
|
-
)
|
182
|
-
self._supported_functions.add(node.name)
|
183
|
-
self.generic_visit(node)
|
201
|
+
@classmethod
|
202
|
+
def rewrite_ast(cls, expression_ast: AST) -> AST:
|
203
|
+
return expression_ast
|
184
204
|
|
185
205
|
|
186
206
|
def validate_expression(
|
187
207
|
expression: str,
|
188
208
|
*,
|
189
|
-
supported_nodes:
|
209
|
+
supported_nodes: tuple[type[AST], ...] = DEFAULT_SUPPORTED_NODE_TYPES,
|
190
210
|
expression_type: str = DEFAULT_EXPRESSION_TYPE,
|
191
|
-
supported_functions: Optional[
|
192
|
-
supported_attr_values: Optional[Set[str]] = None,
|
211
|
+
supported_functions: Optional[set[str]] = None,
|
193
212
|
mode: str = "eval",
|
194
213
|
) -> ast.AST:
|
195
214
|
supported_functions = supported_functions or set(SYMPY_SUPPORTED_EXPRESSIONS).union(
|
@@ -199,7 +218,6 @@ def validate_expression(
|
|
199
218
|
supported_nodes,
|
200
219
|
expression_type,
|
201
220
|
supported_functions,
|
202
|
-
supported_attr_values,
|
203
221
|
mode,
|
204
222
|
)
|
205
223
|
validator.validate(expression)
|
@@ -1,20 +1,25 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
1
|
import abc
|
4
|
-
from
|
2
|
+
from collections.abc import Iterable
|
3
|
+
from typing import ClassVar, Final, Optional
|
5
4
|
|
6
5
|
import pydantic
|
7
6
|
|
8
|
-
from classiq.interface.generator.arith import
|
7
|
+
from classiq.interface.generator.arith.machine_precision import (
|
8
|
+
DEFAULT_MACHINE_PRECISION,
|
9
|
+
)
|
9
10
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
10
11
|
from classiq.interface.generator.function_params import FunctionParams
|
11
12
|
|
12
|
-
|
13
|
+
IMPLICIT_OUTPUTS: Final[str] = "implicit_outputs"
|
14
|
+
DEFAULT_GARBAGE_OUT_NAME: Final[str] = "extra_qubits"
|
15
|
+
MODULO_WITH_FRACTION_PLACES_ERROR_MSG: Final[str] = (
|
16
|
+
"Modulo with fraction places not supported"
|
17
|
+
)
|
13
18
|
|
14
19
|
|
15
20
|
class ArithmeticOperationParams(FunctionParams):
|
16
|
-
output_size: Optional[pydantic.PositiveInt]
|
17
|
-
machine_precision: pydantic.PositiveInt =
|
21
|
+
output_size: Optional[pydantic.PositiveInt] = pydantic.Field(default=None)
|
22
|
+
machine_precision: pydantic.PositiveInt = DEFAULT_MACHINE_PRECISION
|
18
23
|
output_name: ClassVar[str]
|
19
24
|
garbage_output_name: ClassVar[str] = DEFAULT_GARBAGE_OUT_NAME
|
20
25
|
_result_register: Optional[RegisterArithmeticInfo] = pydantic.PrivateAttr(
|
@@ -40,17 +45,15 @@ class ArithmeticOperationParams(FunctionParams):
|
|
40
45
|
return self.output_size is None
|
41
46
|
|
42
47
|
def _legal_bounds(
|
43
|
-
self, suggested_bounds:
|
44
|
-
) -> Optional[
|
45
|
-
if self.
|
48
|
+
self, suggested_bounds: tuple[float, float], max_bounds: tuple[float, float]
|
49
|
+
) -> Optional[tuple[float, float]]:
|
50
|
+
if self.output_size is None or (
|
51
|
+
suggested_bounds[0] >= max_bounds[0]
|
52
|
+
and suggested_bounds[1] <= max_bounds[1]
|
53
|
+
):
|
46
54
|
return suggested_bounds
|
47
55
|
return None
|
48
56
|
|
49
|
-
def _compute_fraction_places(self, argument: argument_utils.RegisterOrConst) -> int:
|
50
|
-
return argument_utils.fraction_places(
|
51
|
-
argument, machine_precision=self.machine_precision
|
52
|
-
)
|
53
|
-
|
54
57
|
@abc.abstractmethod
|
55
|
-
def get_params_inplace_options(self) -> Iterable[ArithmeticOperationParams]:
|
58
|
+
def get_params_inplace_options(self) -> Iterable["ArithmeticOperationParams"]:
|
56
59
|
pass
|
@@ -1,5 +1,6 @@
|
|
1
|
-
from typing import Callable,
|
1
|
+
from typing import Callable, Optional
|
2
2
|
|
3
|
+
from classiq.interface.exceptions import ClassiqArithmeticError
|
3
4
|
from classiq.interface.generator.arith.argument_utils import (
|
4
5
|
RegisterOrConst as RegisterOrFloat,
|
5
6
|
)
|
@@ -35,12 +36,10 @@ from classiq.interface.generator.arith.logical_ops import LogicalAnd, LogicalOr
|
|
35
36
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
36
37
|
from classiq.interface.generator.arith.unary_ops import BitwiseInvert, Negation
|
37
38
|
|
38
|
-
from classiq.exceptions import ClassiqArithmeticError
|
39
|
-
|
40
39
|
ParamsGetter = Callable[..., ArithmeticOperationParams] # Argument vary
|
41
40
|
|
42
41
|
_TARGET_ERROR_MESSAGE: str = "Target unavailable for the requested operation"
|
43
|
-
_OPERATIONS_ALLOWING_TARGET:
|
42
|
+
_OPERATIONS_ALLOWING_TARGET: frozenset = frozenset(
|
44
43
|
{"And", "Or", "Eq", "NotEq", "Lt", "Gt", "LtE", "GtE"}
|
45
44
|
)
|
46
45
|
|
@@ -56,7 +55,7 @@ def operation_allows_target(operation: str) -> bool:
|
|
56
55
|
def get_params(
|
57
56
|
*,
|
58
57
|
node_id: str,
|
59
|
-
args:
|
58
|
+
args: list[RegisterOrFloat],
|
60
59
|
machine_precision: int,
|
61
60
|
output_size: Optional[int] = None,
|
62
61
|
inplace_arg: Optional[str] = None,
|
@@ -331,7 +330,7 @@ def less_equal_params_getter(
|
|
331
330
|
|
332
331
|
|
333
332
|
def logical_and_params_getter(
|
334
|
-
*arg:
|
333
|
+
*arg: list[RegisterOrFloat],
|
335
334
|
machine_precision: int,
|
336
335
|
output_size: Optional[int] = None,
|
337
336
|
inplace_arg: Optional[str] = None,
|
@@ -341,7 +340,7 @@ def logical_and_params_getter(
|
|
341
340
|
|
342
341
|
|
343
342
|
def logical_or_params_getter(
|
344
|
-
*arg:
|
343
|
+
*arg: list[RegisterOrFloat],
|
345
344
|
machine_precision: int,
|
346
345
|
output_size: Optional[int] = None,
|
347
346
|
inplace_arg: Optional[str] = None,
|
@@ -435,7 +434,7 @@ def modulo_params_getter(
|
|
435
434
|
)
|
436
435
|
|
437
436
|
|
438
|
-
params_getter_map:
|
437
|
+
params_getter_map: dict[str, ParamsGetter] = dict(
|
439
438
|
BitOr=or_params_getter,
|
440
439
|
BitAnd=and_params_getter,
|
441
440
|
BitXor=xor_params_getter,
|
@@ -1,15 +1,14 @@
|
|
1
|
-
from typing import Any,
|
1
|
+
from typing import Any, Optional
|
2
2
|
|
3
3
|
import networkx as nx
|
4
4
|
|
5
|
+
from classiq.interface.exceptions import ClassiqArithmeticError
|
5
6
|
from classiq.interface.generator.arith import arithmetic_param_getters, number_utils
|
6
7
|
from classiq.interface.generator.arith.argument_utils import RegisterOrConst
|
7
8
|
from classiq.interface.generator.arith.ast_node_rewrite import OUTPUT_SIZE
|
8
9
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
ArithmeticDefinitions = Dict[str, RegisterOrConst]
|
11
|
+
ArithmeticDefinitions = dict[str, RegisterOrConst]
|
13
12
|
|
14
13
|
|
15
14
|
class ArithmeticResultBuilder:
|
@@ -20,7 +19,7 @@ class ArithmeticResultBuilder:
|
|
20
19
|
definitions: ArithmeticDefinitions,
|
21
20
|
machine_precision: int,
|
22
21
|
) -> None:
|
23
|
-
self.result = self._fill_operation_results(
|
22
|
+
self.result, self.garbage = self._fill_operation_results(
|
24
23
|
graph=graph,
|
25
24
|
result_definitions=definitions,
|
26
25
|
machine_precision=machine_precision,
|
@@ -44,10 +43,10 @@ class ArithmeticResultBuilder:
|
|
44
43
|
def _compute_inputs_data(
|
45
44
|
cls,
|
46
45
|
*,
|
47
|
-
inputs_node_set:
|
46
|
+
inputs_node_set: set[Any],
|
48
47
|
result_definitions: ArithmeticDefinitions,
|
49
48
|
machine_precision: int,
|
50
|
-
) ->
|
49
|
+
) -> dict[str, RegisterOrConst]:
|
51
50
|
return {
|
52
51
|
cls._convert_int_to_float_str(node): cls.convert_result_definition(
|
53
52
|
node, result_definitions.get(node), machine_precision
|
@@ -62,11 +61,11 @@ class ArithmeticResultBuilder:
|
|
62
61
|
graph: nx.DiGraph,
|
63
62
|
result_definitions: ArithmeticDefinitions,
|
64
63
|
machine_precision: int,
|
65
|
-
) -> RegisterArithmeticInfo:
|
66
|
-
inputs_node_set:
|
64
|
+
) -> tuple[RegisterArithmeticInfo, Optional[RegisterArithmeticInfo]]:
|
65
|
+
inputs_node_set: set[str] = {
|
67
66
|
vertex for vertex, deg in graph.in_degree if deg == 0
|
68
67
|
}
|
69
|
-
node_results:
|
68
|
+
node_results: dict[str, RegisterOrConst] = cls._compute_inputs_data(
|
70
69
|
inputs_node_set=inputs_node_set,
|
71
70
|
result_definitions=result_definitions,
|
72
71
|
machine_precision=machine_precision,
|
@@ -80,29 +79,34 @@ class ArithmeticResultBuilder:
|
|
80
79
|
for predecessor_node in graph.predecessors(node)
|
81
80
|
]
|
82
81
|
if graph.out_degree(node) == 0:
|
83
|
-
return cls.
|
82
|
+
return cls._get_node_result_and_garbage(
|
84
83
|
graph, args, node, machine_precision=machine_precision
|
85
84
|
)
|
86
|
-
node_results[node] = cls.
|
85
|
+
node_results[node], _ = cls._get_node_result_and_garbage(
|
87
86
|
graph, args, node, machine_precision=machine_precision
|
88
87
|
)
|
89
88
|
raise ClassiqArithmeticError("Expression has no result")
|
90
89
|
|
91
90
|
@classmethod
|
92
|
-
def
|
91
|
+
def _get_node_result_and_garbage(
|
93
92
|
cls,
|
94
93
|
graph: nx.DiGraph,
|
95
|
-
args:
|
94
|
+
args: list[RegisterOrConst],
|
96
95
|
node: str,
|
97
96
|
*,
|
98
97
|
machine_precision: int,
|
99
|
-
) -> RegisterArithmeticInfo:
|
100
|
-
|
98
|
+
) -> tuple[RegisterArithmeticInfo, Optional[RegisterArithmeticInfo]]:
|
99
|
+
node_params = arithmetic_param_getters.get_params(
|
101
100
|
node_id=node,
|
102
101
|
args=args,
|
103
102
|
output_size=graph.nodes[node].get(OUTPUT_SIZE, None),
|
104
103
|
machine_precision=machine_precision,
|
105
|
-
)
|
104
|
+
)
|
105
|
+
|
106
|
+
return (
|
107
|
+
node_params.outputs[node_params.output_name],
|
108
|
+
node_params.outputs.get(node_params.garbage_output_name),
|
109
|
+
)
|
106
110
|
|
107
111
|
@staticmethod
|
108
112
|
def _convert_int_to_float_str(node: Any) -> str:
|