classiq 0.38.0__py3-none-any.whl → 0.65.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/__init__.py +47 -32
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
- classiq/_internals/api_wrapper.py +235 -97
- classiq/_internals/async_utils.py +1 -3
- classiq/_internals/authentication/auth0.py +26 -10
- classiq/_internals/authentication/authentication.py +11 -0
- classiq/_internals/authentication/device.py +10 -5
- classiq/_internals/authentication/password_manager.py +18 -6
- classiq/_internals/authentication/token_manager.py +10 -5
- classiq/_internals/client.py +94 -33
- classiq/_internals/config.py +3 -4
- classiq/_internals/host_checker.py +38 -15
- classiq/_internals/jobs.py +60 -57
- classiq/_internals/type_validation.py +9 -9
- classiq/analyzer/__init__.py +1 -3
- classiq/analyzer/analyzer.py +24 -19
- classiq/analyzer/analyzer_utilities.py +10 -10
- classiq/analyzer/rb.py +15 -15
- classiq/analyzer/show_interactive_hack.py +27 -4
- classiq/analyzer/url_utils.py +2 -3
- classiq/applications/__init__.py +3 -12
- classiq/applications/chemistry/__init__.py +14 -10
- classiq/applications/chemistry/ansatz_parameters.py +4 -4
- classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +165 -158
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +4 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +51 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +12 -12
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +8 -6
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +7 -11
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +67 -40
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
- classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +2 -2
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +15 -20
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +14 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +11 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +1 -2
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +2 -3
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +5 -8
- classiq/applications/combinatorial_optimization/__init__.py +20 -6
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
- classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +35 -33
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
- classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
- classiq/applications/finance/__init__.py +4 -5
- classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +48 -42
- classiq/applications/grover/__init__.py +9 -0
- classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +52 -51
- classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
- classiq/applications/libraries/qmci_library.py +22 -0
- classiq/applications/qnn/__init__.py +2 -4
- classiq/applications/qnn/circuit_utils.py +6 -6
- classiq/applications/qnn/datasets/__init__.py +9 -11
- classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
- classiq/applications/qnn/datasets/dataset_not.py +2 -1
- classiq/applications/qnn/datasets/dataset_parity.py +2 -2
- classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
- classiq/applications/qnn/qlayer.py +30 -10
- classiq/applications/qnn/torch_utils.py +4 -3
- classiq/applications/qnn/types.py +5 -5
- classiq/applications/qsvm/__init__.py +6 -4
- classiq/applications/qsvm/qsvm.py +3 -6
- classiq/applications/qsvm/qsvm_data_generation.py +3 -3
- classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
- classiq/execution/__init__.py +8 -3
- classiq/execution/all_hardware_devices.py +11 -0
- classiq/execution/execution_session.py +400 -0
- classiq/execution/iqcc.py +63 -0
- classiq/execution/jobs.py +197 -25
- classiq/execution/qnn.py +79 -0
- classiq/executor.py +20 -115
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +43 -13
- classiq/interface/analyzer/cytoscape_graph.py +15 -9
- classiq/interface/analyzer/result.py +28 -32
- classiq/interface/applications/qsvm.py +20 -29
- classiq/interface/ast_node.py +16 -0
- classiq/interface/backend/backend_preferences.py +390 -121
- classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
- classiq/interface/backend/pydantic_backend.py +25 -22
- classiq/interface/backend/quantum_backend_providers.py +69 -16
- classiq/interface/chemistry/fermionic_operator.py +30 -21
- classiq/interface/chemistry/ground_state_problem.py +28 -25
- classiq/interface/chemistry/molecule.py +14 -10
- classiq/interface/chemistry/operator.py +64 -231
- classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
- classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
- classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
- classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
- classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +8 -9
- classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
- classiq/interface/combinatorial_optimization/result.py +1 -3
- classiq/interface/combinatorial_optimization/solver_types.py +1 -1
- classiq/interface/debug_info/debug_info.py +86 -0
- classiq/{exceptions.py → interface/exceptions.py} +37 -9
- classiq/interface/execution/iqcc.py +19 -0
- classiq/interface/execution/jobs.py +15 -12
- classiq/interface/execution/primitives.py +18 -0
- classiq/interface/executor/constants.py +1 -0
- classiq/interface/executor/execution_preferences.py +26 -114
- classiq/interface/executor/execution_request.py +24 -46
- classiq/interface/executor/execution_result.py +30 -8
- classiq/interface/executor/iqae_result.py +4 -6
- classiq/interface/executor/optimizer_preferences.py +17 -14
- classiq/interface/executor/quantum_code.py +28 -24
- classiq/interface/executor/quantum_instruction_set.py +2 -2
- classiq/interface/executor/register_initialization.py +11 -14
- classiq/interface/executor/result.py +83 -56
- classiq/interface/executor/vqe_result.py +10 -10
- classiq/interface/finance/function_input.py +35 -25
- classiq/interface/finance/gaussian_model_input.py +5 -5
- classiq/interface/finance/log_normal_model_input.py +4 -4
- classiq/interface/finance/model_input.py +4 -4
- classiq/interface/generator/adjacency.py +1 -3
- classiq/interface/generator/amplitude_loading.py +22 -12
- classiq/interface/generator/ansatz_library.py +5 -5
- classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
- classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
- classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
- classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
- classiq/interface/generator/application_apis/finance_declarations.py +48 -69
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
- classiq/interface/generator/arith/argument_utils.py +46 -5
- classiq/interface/generator/arith/arithmetic.py +35 -16
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +6 -7
- classiq/interface/generator/arith/arithmetic_expression_abc.py +66 -25
- classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -11
- classiq/interface/generator/arith/arithmetic_expression_validator.py +47 -43
- classiq/interface/generator/arith/arithmetic_operations.py +14 -6
- classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
- classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
- classiq/interface/generator/arith/ast_node_rewrite.py +3 -2
- classiq/interface/generator/arith/binary_ops.py +218 -130
- classiq/interface/generator/arith/endianness.py +1 -1
- classiq/interface/generator/arith/extremum_operations.py +96 -25
- classiq/interface/generator/arith/logical_ops.py +14 -12
- classiq/interface/generator/arith/number_utils.py +12 -6
- classiq/interface/generator/arith/register_user_input.py +60 -37
- classiq/interface/generator/arith/unary_ops.py +49 -29
- classiq/interface/generator/arith/uncomputation_methods.py +1 -1
- classiq/interface/generator/builtin_api_builder.py +2 -9
- classiq/interface/generator/chemistry_function_params.py +3 -3
- classiq/interface/generator/circuit_code/circuit_code.py +7 -7
- classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
- classiq/interface/generator/commuting_pauli_exponentiation.py +7 -7
- classiq/interface/generator/compiler_keywords.py +5 -1
- classiq/interface/generator/complex_type.py +13 -18
- classiq/interface/generator/constant.py +3 -4
- classiq/interface/generator/control_state.py +34 -29
- classiq/interface/generator/copy.py +47 -0
- classiq/interface/generator/custom_ansatz.py +2 -5
- classiq/interface/generator/distance.py +3 -5
- classiq/interface/generator/excitations.py +3 -2
- classiq/interface/generator/expressions/atomic_expression_functions.py +21 -5
- classiq/interface/generator/expressions/enums/__init__.py +0 -10
- classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
- classiq/interface/generator/expressions/evaluated_expression.py +5 -5
- classiq/interface/generator/expressions/expression.py +26 -14
- classiq/interface/generator/expressions/expression_constants.py +9 -3
- classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +34 -8
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
- classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
- classiq/interface/generator/expressions/sympy_supported_expressions.py +19 -11
- classiq/interface/generator/finance.py +2 -2
- classiq/interface/generator/function_param_library.py +6 -6
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
- classiq/interface/generator/function_params.py +36 -64
- classiq/interface/generator/functions/__init__.py +0 -22
- classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
- classiq/interface/generator/functions/classical_function_declaration.py +18 -9
- classiq/interface/generator/functions/classical_type.py +47 -166
- classiq/interface/generator/functions/concrete_types.py +55 -0
- classiq/interface/generator/functions/function_declaration.py +13 -14
- classiq/interface/generator/functions/port_declaration.py +1 -13
- classiq/interface/generator/functions/qmod_python_interface.py +2 -1
- classiq/interface/generator/functions/type_name.py +90 -0
- classiq/interface/generator/generated_circuit_data.py +153 -20
- classiq/interface/generator/grover_diffuser.py +32 -25
- classiq/interface/generator/grover_operator.py +34 -25
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +9 -9
- classiq/interface/generator/hardware/hardware_data.py +72 -34
- classiq/interface/generator/hardware_efficient_ansatz.py +20 -16
- classiq/interface/generator/hartree_fock.py +13 -5
- classiq/interface/generator/identity.py +10 -6
- classiq/interface/generator/linear_pauli_rotations.py +32 -20
- classiq/interface/generator/mcmt_method.py +1 -1
- classiq/interface/generator/mcu.py +17 -15
- classiq/interface/generator/mcx.py +24 -17
- classiq/interface/generator/model/__init__.py +2 -5
- classiq/interface/generator/model/constraints.py +26 -8
- classiq/interface/generator/model/model.py +27 -190
- classiq/interface/generator/model/preferences/preferences.py +115 -41
- classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +14 -17
- classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
- classiq/interface/generator/oracles/custom_oracle.py +15 -13
- classiq/interface/generator/oracles/oracle_abc.py +7 -7
- classiq/interface/generator/partitioned_register.py +7 -7
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
- classiq/interface/generator/preferences/optimization.py +1 -2
- classiq/interface/generator/qpe.py +41 -30
- classiq/interface/generator/qsvm.py +9 -10
- classiq/interface/generator/quantum_function_call.py +88 -73
- classiq/interface/generator/quantum_program.py +41 -24
- classiq/interface/generator/range_types.py +11 -12
- classiq/interface/generator/register_role.py +18 -6
- classiq/interface/generator/slice_parsing_utils.py +5 -5
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +30 -39
- classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
- classiq/interface/generator/standard_gates/standard_gates.py +3 -3
- classiq/interface/generator/standard_gates/u_gate.py +7 -10
- classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
- classiq/interface/generator/state_preparation/distributions.py +16 -15
- classiq/interface/generator/state_preparation/metrics.py +4 -7
- classiq/interface/generator/state_preparation/state_preparation.py +25 -20
- classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
- classiq/interface/generator/transpiler_basis_gates.py +7 -3
- classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
- classiq/interface/generator/types/compilation_metadata.py +6 -0
- classiq/interface/generator/types/enum_declaration.py +54 -0
- classiq/interface/generator/types/qstruct_declaration.py +18 -0
- classiq/interface/generator/types/struct_declaration.py +7 -11
- classiq/interface/generator/ucc.py +5 -4
- classiq/interface/generator/unitary_gate.py +5 -5
- classiq/interface/generator/user_defined_function_params.py +4 -1
- classiq/interface/generator/validations/flow_graph.py +7 -7
- classiq/interface/generator/validations/validator_functions.py +4 -4
- classiq/interface/generator/visitor.py +23 -16
- classiq/interface/hardware.py +29 -8
- classiq/interface/helpers/classproperty.py +8 -0
- classiq/interface/helpers/custom_encoders.py +2 -2
- classiq/interface/helpers/custom_pydantic_types.py +40 -50
- classiq/interface/helpers/datastructures.py +26 -0
- classiq/interface/helpers/hashable_mixin.py +3 -2
- classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
- classiq/interface/helpers/pydantic_model_helpers.py +7 -5
- classiq/interface/helpers/validation_helpers.py +3 -20
- classiq/interface/helpers/versioned_model.py +1 -4
- classiq/interface/ide/ide_data.py +16 -20
- classiq/interface/ide/visual_model.py +130 -0
- classiq/interface/interface_version.py +1 -0
- classiq/interface/jobs.py +29 -69
- classiq/interface/model/allocate.py +16 -0
- classiq/interface/model/bind_operation.py +32 -9
- classiq/interface/model/classical_if.py +15 -0
- classiq/interface/model/classical_parameter_declaration.py +33 -3
- classiq/interface/model/control.py +45 -0
- classiq/interface/model/handle_binding.py +298 -20
- classiq/interface/model/inplace_binary_operation.py +29 -24
- classiq/interface/model/invert.py +12 -0
- classiq/interface/model/model.py +69 -61
- classiq/interface/model/native_function_definition.py +17 -20
- classiq/interface/model/parameter.py +13 -0
- classiq/interface/model/phase_operation.py +11 -0
- classiq/interface/model/port_declaration.py +27 -9
- classiq/interface/model/power.py +14 -0
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +30 -18
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
- classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
- classiq/interface/model/quantum_function_call.py +141 -343
- classiq/interface/model/quantum_function_declaration.py +190 -157
- classiq/interface/model/quantum_lambda_function.py +33 -32
- classiq/interface/model/quantum_statement.py +71 -12
- classiq/interface/model/quantum_type.py +177 -40
- classiq/interface/model/quantum_variable_declaration.py +3 -25
- classiq/interface/model/repeat.py +15 -0
- classiq/interface/model/statement_block.py +40 -14
- classiq/interface/model/validation_handle.py +13 -6
- classiq/interface/model/variable_declaration_statement.py +3 -1
- classiq/interface/model/within_apply_operation.py +7 -5
- classiq/interface/server/global_versions.py +6 -7
- classiq/interface/server/routes.py +17 -21
- classiq/interface/source_reference.py +59 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
- classiq/model_expansions/capturing/__init__.py +0 -0
- classiq/model_expansions/capturing/captured_vars.py +435 -0
- classiq/model_expansions/capturing/mangling_utils.py +56 -0
- classiq/model_expansions/closure.py +171 -0
- classiq/model_expansions/debug_flag.py +3 -0
- classiq/model_expansions/evaluators/__init__.py +0 -0
- classiq/model_expansions/evaluators/arg_type_match.py +158 -0
- classiq/model_expansions/evaluators/argument_types.py +42 -0
- classiq/model_expansions/evaluators/classical_expression.py +36 -0
- classiq/model_expansions/evaluators/control.py +144 -0
- classiq/model_expansions/evaluators/parameter_types.py +226 -0
- classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
- classiq/model_expansions/evaluators/type_type_match.py +90 -0
- classiq/model_expansions/expression_evaluator.py +135 -0
- classiq/model_expansions/expression_renamer.py +76 -0
- classiq/model_expansions/function_builder.py +247 -0
- classiq/model_expansions/generative_functions.py +158 -0
- classiq/model_expansions/interpreters/__init__.py +0 -0
- classiq/model_expansions/interpreters/base_interpreter.py +263 -0
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
- classiq/model_expansions/model_tables.py +18 -0
- classiq/model_expansions/quantum_operations/__init__.py +9 -0
- classiq/model_expansions/quantum_operations/bind.py +60 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
- classiq/model_expansions/quantum_operations/classicalif.py +53 -0
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
- classiq/model_expansions/quantum_operations/emitter.py +181 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
- classiq/model_expansions/quantum_operations/repeat.py +56 -0
- classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
- classiq/model_expansions/scope.py +240 -0
- classiq/model_expansions/scope_initialization.py +150 -0
- classiq/model_expansions/sympy_conversion/__init__.py +0 -0
- classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
- classiq/model_expansions/transformers/__init__.py +0 -0
- classiq/model_expansions/transformers/ast_renamer.py +26 -0
- classiq/model_expansions/transformers/var_splitter.py +299 -0
- classiq/model_expansions/utils/__init__.py +0 -0
- classiq/model_expansions/utils/counted_name_allocator.py +11 -0
- classiq/model_expansions/utils/handles_collector.py +33 -0
- classiq/model_expansions/visitors/__init__.py +0 -0
- classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
- classiq/model_expansions/visitors/variable_references.py +144 -0
- classiq/open_library/__init__.py +4 -0
- classiq/open_library/functions/__init__.py +130 -0
- classiq/open_library/functions/amplitude_estimation.py +30 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
- classiq/open_library/functions/grover.py +157 -0
- classiq/open_library/functions/hea.py +115 -0
- classiq/open_library/functions/linear_pauli_rotation.py +82 -0
- classiq/open_library/functions/modular_exponentiation.py +201 -0
- classiq/open_library/functions/qaoa_penalty.py +117 -0
- classiq/open_library/functions/qft_functions.py +54 -0
- classiq/open_library/functions/qpe.py +46 -0
- classiq/open_library/functions/qsvt.py +331 -0
- classiq/open_library/functions/state_preparation.py +301 -0
- classiq/open_library/functions/swap_test.py +27 -0
- classiq/open_library/functions/utility_functions.py +81 -0
- classiq/open_library/functions/variational.py +52 -0
- classiq/qmod/__init__.py +10 -10
- classiq/qmod/builtins/__init__.py +19 -2
- classiq/qmod/builtins/classical_execution_primitives.py +36 -14
- classiq/qmod/builtins/classical_functions.py +39 -43
- classiq/qmod/builtins/constants.py +10 -0
- classiq/qmod/builtins/enums.py +208 -0
- classiq/qmod/builtins/functions/__init__.py +137 -0
- classiq/qmod/builtins/functions/allocation.py +150 -0
- classiq/qmod/builtins/functions/arithmetic.py +55 -0
- classiq/qmod/builtins/functions/benchmarking.py +8 -0
- classiq/qmod/builtins/functions/chemistry.py +91 -0
- classiq/qmod/builtins/functions/exponentiation.py +105 -0
- classiq/qmod/builtins/functions/finance.py +34 -0
- classiq/qmod/builtins/functions/operators.py +16 -0
- classiq/qmod/builtins/functions/qsvm.py +24 -0
- classiq/qmod/builtins/functions/standard_gates.py +651 -0
- classiq/qmod/builtins/operations.py +373 -40
- classiq/qmod/builtins/structs.py +103 -80
- classiq/qmod/cfunc.py +2 -2
- classiq/qmod/classical_function.py +4 -8
- classiq/qmod/cparam.py +64 -0
- classiq/qmod/create_model_function.py +56 -0
- classiq/qmod/declaration_inferrer.py +143 -101
- classiq/qmod/expression_query.py +20 -4
- classiq/qmod/generative.py +42 -0
- classiq/qmod/model_state_container.py +18 -6
- classiq/qmod/native/__init__.py +7 -0
- classiq/qmod/native/expression_to_qmod.py +16 -11
- classiq/qmod/native/pretty_printer.py +187 -97
- classiq/qmod/pretty_print/__init__.py +7 -0
- classiq/qmod/pretty_print/expression_to_python.py +222 -0
- classiq/qmod/pretty_print/pretty_printer.py +572 -0
- classiq/qmod/python_classical_type.py +67 -0
- classiq/qmod/qfunc.py +60 -8
- classiq/qmod/qmod_constant.py +93 -26
- classiq/qmod/qmod_parameter.py +68 -59
- classiq/qmod/qmod_variable.py +468 -155
- classiq/qmod/quantum_callable.py +17 -7
- classiq/qmod/quantum_expandable.py +269 -96
- classiq/qmod/quantum_function.py +196 -41
- classiq/qmod/semantics/__init__.py +0 -0
- classiq/qmod/semantics/annotation/__init__.py +0 -0
- classiq/qmod/semantics/annotation/call_annotation.py +92 -0
- classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
- classiq/qmod/semantics/error_manager.py +88 -0
- classiq/qmod/semantics/lambdas.py +25 -0
- classiq/qmod/semantics/static_semantics_visitor.py +384 -0
- classiq/qmod/semantics/validation/__init__.py +0 -0
- classiq/qmod/semantics/validation/constants_validation.py +16 -0
- classiq/qmod/semantics/validation/func_call_validation.py +99 -0
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
- classiq/qmod/semantics/validation/handle_validation.py +85 -0
- classiq/qmod/semantics/validation/main_validation.py +33 -0
- classiq/qmod/semantics/validation/types_validation.py +128 -0
- classiq/qmod/symbolic.py +147 -123
- classiq/qmod/symbolic_expr.py +27 -12
- classiq/qmod/symbolic_type.py +2 -5
- classiq/qmod/type_attribute_remover.py +32 -0
- classiq/qmod/utilities.py +98 -4
- classiq/qmod/write_qmod.py +17 -3
- classiq/synthesis.py +210 -22
- {classiq-0.38.0.dist-info → classiq-0.65.4.dist-info}/METADATA +16 -9
- classiq-0.65.4.dist-info/RECORD +521 -0
- classiq/_internals/_qfunc_ext.py +0 -6
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -25
- classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -65
- classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +0 -243
- classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
- classiq/builtin_functions/__init__.py +0 -43
- classiq/builtin_functions/amplitude_loading.py +0 -3
- classiq/builtin_functions/binary_ops.py +0 -1
- classiq/builtin_functions/exponentiation.py +0 -5
- classiq/builtin_functions/qpe.py +0 -4
- classiq/builtin_functions/qsvm.py +0 -7
- classiq/builtin_functions/range_types.py +0 -5
- classiq/builtin_functions/standard_gates.py +0 -1
- classiq/builtin_functions/state_preparation.py +0 -6
- classiq/builtin_functions/suzuki_trotter.py +0 -3
- classiq/interface/executor/aws_execution_cost.py +0 -73
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
- classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
- classiq/interface/generator/expressions/enums/chemistry.py +0 -28
- classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
- classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
- classiq/interface/generator/expressions/enums/optimizers.py +0 -9
- classiq/interface/generator/expressions/enums/pauli.py +0 -8
- classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -1229
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
- classiq/interface/generator/functions/foreign_function_definition.py +0 -114
- classiq/interface/generator/functions/function_implementation.py +0 -107
- classiq/interface/generator/functions/native_function_definition.py +0 -155
- classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
- classiq/interface/generator/functions/register.py +0 -44
- classiq/interface/generator/functions/register_mapping_data.py +0 -106
- classiq/interface/generator/inequality_mixer.py +0 -51
- classiq/interface/generator/model/classical_main_validator.py +0 -106
- classiq/interface/generator/range_mixer.py +0 -56
- classiq/interface/generator/state_propagator.py +0 -74
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
- classiq/interface/ide/show.py +0 -34
- classiq/interface/model/call_synthesis_data.py +0 -68
- classiq/interface/model/common_model_types.py +0 -23
- classiq/interface/model/quantum_expressions/control_state.py +0 -38
- classiq/interface/model/quantum_if_operation.py +0 -94
- classiq/interface/model/resolvers/function_call_resolver.py +0 -43
- classiq/interface/model/validations/handle_validation_base.py +0 -55
- classiq/interface/model/validations/handles_validator.py +0 -156
- classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
- classiq/model/__init__.py +0 -14
- classiq/model/composite_function_generator.py +0 -33
- classiq/model/function_handler.py +0 -462
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -229
- classiq/qmod/builtins/functions.py +0 -913
- classiq/qmod/qmod_struct.py +0 -37
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -205
- classiq/quantum_functions/decorators.py +0 -22
- classiq/quantum_functions/function_library.py +0 -181
- classiq/quantum_functions/function_parser.py +0 -74
- classiq/quantum_functions/quantum_function.py +0 -236
- classiq-0.38.0.dist-info/RECORD +0 -454
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
- /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
- /classiq/{interface/generator/credit_risk_example → applications/hamiltonian}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
- /classiq/interface/{model/resolvers → debug_info}/__init__.py +0 -0
- /classiq/{_internals → interface}/enum_utils.py +0 -0
- /classiq/interface/{model/validations → generator/functions/builtins}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → model_expansions/__init__.py} +0 -0
- {classiq-0.38.0.dist-info → classiq-0.65.4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,447 @@
|
|
1
|
+
import math
|
2
|
+
import re
|
3
|
+
from collections import defaultdict
|
4
|
+
from collections.abc import Iterator
|
5
|
+
from contextlib import contextmanager
|
6
|
+
from enum import Enum
|
7
|
+
from functools import reduce
|
8
|
+
from operator import mul
|
9
|
+
from typing import Any, Optional, TypeVar, Union
|
10
|
+
|
11
|
+
import pydantic
|
12
|
+
import pyomo.core.expr.numeric_expr as pyo_expr
|
13
|
+
import pyomo.environ as pyo
|
14
|
+
import sympy
|
15
|
+
from pyomo.core import ConcreteModel, Constraint, Objective, Var, maximize
|
16
|
+
from pyomo.core.base import _GeneralVarData
|
17
|
+
from pyomo.core.base.component import ComponentData
|
18
|
+
from pyomo.core.base.constraint import _GeneralConstraintData
|
19
|
+
from pyomo.core.base.indexed_component import IndexedComponent
|
20
|
+
from pyomo.core.base.objective import ScalarObjective
|
21
|
+
from pyomo.core.expr.base import ExpressionBase
|
22
|
+
from pyomo.core.expr.sympy_tools import (
|
23
|
+
Pyomo2SympyVisitor,
|
24
|
+
PyomoSympyBimap,
|
25
|
+
Sympy2PyomoVisitor,
|
26
|
+
)
|
27
|
+
|
28
|
+
from classiq.interface.exceptions import ClassiqValueError
|
29
|
+
from classiq.interface.generator.expressions.expression import Expression
|
30
|
+
from classiq.interface.generator.functions.classical_type import Integer
|
31
|
+
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
32
|
+
|
33
|
+
from classiq.qmod.qmod_variable import QArray, QBit, QNum, QStruct, QVar
|
34
|
+
from classiq.qmod.symbolic_expr import SymbolicExpr
|
35
|
+
|
36
|
+
ListVars = list[_GeneralVarData]
|
37
|
+
SUPPORTED_TYPES = [
|
38
|
+
pyo.Binary,
|
39
|
+
pyo.Integers,
|
40
|
+
pyo.NegativeIntegers,
|
41
|
+
pyo.NonNegativeIntegers,
|
42
|
+
pyo.NonPositiveIntegers,
|
43
|
+
pyo.PositiveIntegers,
|
44
|
+
]
|
45
|
+
|
46
|
+
|
47
|
+
class ObjectiveType(Enum):
|
48
|
+
Min = "Min"
|
49
|
+
Max = "Max"
|
50
|
+
|
51
|
+
|
52
|
+
class CombinatorialOptimizationStructDeclaration(StructDeclaration):
|
53
|
+
variable_lower_bound: int = pydantic.Field(default=0)
|
54
|
+
variable_upper_bound: int = pydantic.Field(default=1)
|
55
|
+
constraints: list[Expression] = pydantic.Field(
|
56
|
+
default_factory=list, description="List of constraint expressions"
|
57
|
+
)
|
58
|
+
objective_type: ObjectiveType = pydantic.Field(
|
59
|
+
description="Specify whether the optimization problem is Min or Max"
|
60
|
+
)
|
61
|
+
objective_function: Expression = pydantic.Field(
|
62
|
+
description="The expression to optimize, according to the objective type"
|
63
|
+
)
|
64
|
+
|
65
|
+
|
66
|
+
def contains(var_data: _GeneralVarData, vars_data: ListVars) -> bool:
|
67
|
+
# HACK: standard "__containts__ (in)" method doesn't work, because pyomo overrode the __eq__ method (IMO)
|
68
|
+
return any(var_data is var_data_temp for var_data_temp in vars_data)
|
69
|
+
|
70
|
+
|
71
|
+
def remove(var_data: _GeneralVarData, vars_data: ListVars) -> ListVars:
|
72
|
+
# HACK: standard "list method remove" method doesn't work, because pyomo overrode the __eq__ method (IMO)
|
73
|
+
assert contains(var_data, vars_data), "var not in list"
|
74
|
+
vars_data = vars_data.copy()
|
75
|
+
for idx, var_data_temp in enumerate(vars_data):
|
76
|
+
if var_data_temp is var_data:
|
77
|
+
del vars_data[idx]
|
78
|
+
break
|
79
|
+
return vars_data
|
80
|
+
|
81
|
+
|
82
|
+
def index(var_data: _GeneralVarData, vars_data: ListVars) -> int:
|
83
|
+
# HACK: standard "index method" doesn't work.
|
84
|
+
assert contains(var_data, vars_data), "var not in list"
|
85
|
+
idxs = [
|
86
|
+
idx for idx, var_data_temp in enumerate(vars_data) if var_data is var_data_temp
|
87
|
+
]
|
88
|
+
return idxs[0]
|
89
|
+
|
90
|
+
|
91
|
+
T = TypeVar("T")
|
92
|
+
|
93
|
+
|
94
|
+
def extract(model: ConcreteModel, type_: type[T]) -> list[T]:
|
95
|
+
if type_ == _GeneralVarData:
|
96
|
+
type_ = Var
|
97
|
+
|
98
|
+
elif type_ == _GeneralConstraintData:
|
99
|
+
type_ = Constraint
|
100
|
+
|
101
|
+
components = model.component_objects(type_)
|
102
|
+
return [
|
103
|
+
component[component_idx]
|
104
|
+
for component in components
|
105
|
+
for component_idx in component
|
106
|
+
]
|
107
|
+
|
108
|
+
|
109
|
+
def delete_component(model: ConcreteModel, component: ComponentData) -> None:
|
110
|
+
parent_ref = component._component
|
111
|
+
|
112
|
+
if parent_ref is None:
|
113
|
+
return
|
114
|
+
|
115
|
+
parent_component = parent_ref()
|
116
|
+
|
117
|
+
if component is parent_component:
|
118
|
+
model.del_component(component)
|
119
|
+
else:
|
120
|
+
_delete_element_by_value(parent_component, component)
|
121
|
+
|
122
|
+
if not parent_component:
|
123
|
+
model.del_component(parent_component)
|
124
|
+
|
125
|
+
|
126
|
+
def _delete_element_by_value(dict_: dict, value: Any) -> None:
|
127
|
+
iter_dict = {**dict_}
|
128
|
+
for k, v in iter_dict.items():
|
129
|
+
if v is value and k in dict_:
|
130
|
+
del dict_[k]
|
131
|
+
|
132
|
+
|
133
|
+
def get_name(component: Union[IndexedComponent, ComponentData]) -> str:
|
134
|
+
if isinstance(component, IndexedComponent):
|
135
|
+
return component._name # constraint.name returns "'{name}'"
|
136
|
+
else:
|
137
|
+
return component.name
|
138
|
+
|
139
|
+
|
140
|
+
class FixedSympy2PyomoVisitor(Sympy2PyomoVisitor):
|
141
|
+
def beforeChild( # noqa: N802
|
142
|
+
self, node: Optional[sympy.Expr], child: sympy.Expr, child_idx: Optional[int]
|
143
|
+
) -> tuple[bool, Union[int, float, None]]:
|
144
|
+
if not child._args:
|
145
|
+
item = self.object_map.getPyomoSymbol(child, None)
|
146
|
+
if item is None:
|
147
|
+
if isinstance(child, sympy.Integer): # addition to base implementation
|
148
|
+
item = int(child.evalf())
|
149
|
+
else:
|
150
|
+
item = float(child.evalf())
|
151
|
+
return False, item
|
152
|
+
return True, None
|
153
|
+
|
154
|
+
|
155
|
+
def sympy2pyomo_expression(
|
156
|
+
expr: sympy.core.Basic, object_map: PyomoSympyBimap
|
157
|
+
) -> pyo_expr.ExpressionBase:
|
158
|
+
return FixedSympy2PyomoVisitor(object_map).walk_expression(expr)
|
159
|
+
|
160
|
+
|
161
|
+
def convert_pyomo_to_global_presentation(
|
162
|
+
pyo_model: pyo.ConcreteModel,
|
163
|
+
) -> pyo.ConcreteModel:
|
164
|
+
problem_struct = pyomo2qmod("nativePyoModel", pyo_model)
|
165
|
+
|
166
|
+
pyomo_model = pyo.ConcreteModel()
|
167
|
+
|
168
|
+
var_names = list(problem_struct.variables.keys())
|
169
|
+
pyomo_model.var_set = pyo.Var(
|
170
|
+
var_names,
|
171
|
+
domain=pyo.NonNegativeIntegers,
|
172
|
+
bounds=(
|
173
|
+
problem_struct.variable_lower_bound,
|
174
|
+
problem_struct.variable_upper_bound,
|
175
|
+
),
|
176
|
+
)
|
177
|
+
obj_map = PyomoSympyBimap()
|
178
|
+
var_dict = {
|
179
|
+
var_name: obj_map.getSympySymbol(pyomo_model.var_set[var_name])
|
180
|
+
for var_name in var_names
|
181
|
+
}
|
182
|
+
|
183
|
+
def expr2pyomo(expr: Expression) -> pyo_expr.ExpressionBase:
|
184
|
+
sp_expr = sympy.sympify(expr.expr, locals=var_dict)
|
185
|
+
if isinstance(sp_expr, sympy.core.relational.Equality):
|
186
|
+
return sympy2pyomo_expression(
|
187
|
+
sp_expr.args[0], obj_map
|
188
|
+
) == sympy2pyomo_expression(sp_expr.args[1], obj_map)
|
189
|
+
|
190
|
+
# Note that strict greater/less than are not supported by Pyomo
|
191
|
+
return sympy2pyomo_expression(sp_expr, obj_map)
|
192
|
+
|
193
|
+
pyomo_model.constraints = pyo.Constraint(
|
194
|
+
pyo.RangeSet(0, len(problem_struct.constraints) - 1),
|
195
|
+
rule=lambda model, i: expr2pyomo(problem_struct.constraints[i]),
|
196
|
+
)
|
197
|
+
pyomo_model.objective = pyo.Objective(
|
198
|
+
expr=expr2pyomo(problem_struct.objective_function),
|
199
|
+
sense=(
|
200
|
+
pyo.maximize
|
201
|
+
if problem_struct.objective_type == ObjectiveType.Max
|
202
|
+
else pyo.minimize
|
203
|
+
),
|
204
|
+
)
|
205
|
+
|
206
|
+
return pyomo_model
|
207
|
+
|
208
|
+
|
209
|
+
def pyomo2qmod(
|
210
|
+
struct_name: str, pyo_model: ConcreteModel
|
211
|
+
) -> CombinatorialOptimizationStructDeclaration:
|
212
|
+
symbols_map = PyomoSympyBimap()
|
213
|
+
|
214
|
+
variables: list[sympy.Symbol] = []
|
215
|
+
|
216
|
+
bounds_set = False
|
217
|
+
lower_bound = None
|
218
|
+
upper_bound = None
|
219
|
+
|
220
|
+
for var_dict in pyo_model.component_objects(Var):
|
221
|
+
for key in var_dict:
|
222
|
+
var = Pyomo2SympyVisitor(symbols_map).walk_expression(var_dict[key])
|
223
|
+
var.name = var.name.replace(",", "_")
|
224
|
+
variables.append(var)
|
225
|
+
if bounds_set:
|
226
|
+
if lower_bound != var_dict[key].lb:
|
227
|
+
raise ClassiqValueError(
|
228
|
+
"All problem variables must agree on lower bound"
|
229
|
+
)
|
230
|
+
if upper_bound != var_dict[key].ub:
|
231
|
+
raise ClassiqValueError(
|
232
|
+
"All problem variables must agree on upper bound"
|
233
|
+
)
|
234
|
+
else:
|
235
|
+
lower_bound = var_dict[key].lb
|
236
|
+
upper_bound = var_dict[key].ub
|
237
|
+
bounds_set = True
|
238
|
+
|
239
|
+
constraint_exprs: list[sympy.Expr] = []
|
240
|
+
|
241
|
+
constraint_exprs.extend(
|
242
|
+
Pyomo2SympyVisitor(symbols_map).walk_expression(constraint_dict[key].expr)
|
243
|
+
for constraint_dict in pyo_model.component_objects(Constraint)
|
244
|
+
for key in constraint_dict
|
245
|
+
)
|
246
|
+
|
247
|
+
pyo_objective: ScalarObjective = next(pyo_model.component_objects(Objective))
|
248
|
+
objective_type_str = "Max" if pyo_objective.sense == maximize else "Min"
|
249
|
+
objective_expr: sympy.Expr = Pyomo2SympyVisitor(symbols_map).walk_expression(
|
250
|
+
pyo_objective
|
251
|
+
)
|
252
|
+
|
253
|
+
return CombinatorialOptimizationStructDeclaration(
|
254
|
+
name=struct_name,
|
255
|
+
variables={str(variable): Integer() for variable in variables},
|
256
|
+
variable_lower_bound=lower_bound,
|
257
|
+
variable_upper_bound=upper_bound,
|
258
|
+
constraints=[
|
259
|
+
Expression(expr=str(constraint_expr))
|
260
|
+
for constraint_expr in constraint_exprs
|
261
|
+
],
|
262
|
+
objective_type=objective_type_str,
|
263
|
+
objective_function=Expression(expr=str(objective_expr)),
|
264
|
+
)
|
265
|
+
|
266
|
+
|
267
|
+
def pyomo_to_qmod_qstruct(
|
268
|
+
struct_name: str, vars: list[_GeneralVarData]
|
269
|
+
) -> type[QStruct]:
|
270
|
+
qmod_struct = type(struct_name, (QStruct,), {})
|
271
|
+
qmod_struct.__annotations__ = _get_qstruct_fields(vars)
|
272
|
+
return qmod_struct
|
273
|
+
|
274
|
+
|
275
|
+
def _get_qstruct_fields(vars: list[_GeneralVarData]) -> dict[str, type[QVar]]:
|
276
|
+
array_type_sizes = _get_array_sizes(vars)
|
277
|
+
fields: dict[str, type[QVar]] = {}
|
278
|
+
for var in vars:
|
279
|
+
_add_qmod_field(var, array_type_sizes, fields)
|
280
|
+
return fields
|
281
|
+
|
282
|
+
|
283
|
+
def _get_array_sizes(vars: list[_GeneralVarData]) -> dict[str, tuple[int, ...]]:
|
284
|
+
array_types: dict[str, set[tuple]] = defaultdict(set)
|
285
|
+
for var in vars:
|
286
|
+
if is_index_var(var):
|
287
|
+
array_types[get_field_name(var.parent_component())].add(
|
288
|
+
index_as_tuple(var.index())
|
289
|
+
)
|
290
|
+
return {
|
291
|
+
name: dimensions
|
292
|
+
for name, indices in array_types.items()
|
293
|
+
if (dimensions := _get_indices_dimensions(indices)) is not None
|
294
|
+
}
|
295
|
+
|
296
|
+
|
297
|
+
def _get_indices_dimensions(indices: set[tuple[int, ...]]) -> Optional[tuple[int, ...]]:
|
298
|
+
indices_list = list(indices)
|
299
|
+
if len(indices) == 0:
|
300
|
+
return None
|
301
|
+
first_idx = indices_list[0]
|
302
|
+
if len(first_idx) == 0:
|
303
|
+
return None
|
304
|
+
if any(len(idx) != len(first_idx) for idx in indices_list[1:]):
|
305
|
+
return None
|
306
|
+
dimension_bounds = [(idx, idx) for idx in first_idx]
|
307
|
+
for multi_idx in indices_list[1:]:
|
308
|
+
for dim_idx, idx in enumerate(multi_idx):
|
309
|
+
dimension_bounds[dim_idx] = (
|
310
|
+
min(dimension_bounds[dim_idx][0], idx),
|
311
|
+
max(dimension_bounds[dim_idx][1], idx),
|
312
|
+
)
|
313
|
+
if any(lb != 0 for lb, ub in dimension_bounds):
|
314
|
+
return None
|
315
|
+
dimensions = tuple(ub + 1 for _, ub in dimension_bounds)
|
316
|
+
if reduce(mul, dimensions) != len(indices_list):
|
317
|
+
return None
|
318
|
+
return dimensions
|
319
|
+
|
320
|
+
|
321
|
+
def _add_qmod_field(
|
322
|
+
var: _GeneralVarData,
|
323
|
+
array_type_sizes: dict[str, tuple[int, ...]],
|
324
|
+
fields: dict[str, type[QVar]],
|
325
|
+
) -> None:
|
326
|
+
parent_name = get_field_name(var.parent_component())
|
327
|
+
if parent_name not in array_type_sizes:
|
328
|
+
var_name = get_field_name(var)
|
329
|
+
fields[var_name] = _get_qmod_field_type(var_name, var)
|
330
|
+
return
|
331
|
+
dimensions = array_type_sizes[parent_name]
|
332
|
+
if index_as_tuple(var.index()) == tuple(0 for _ in range(len(dimensions))):
|
333
|
+
qmod_type: type[QVar] = _get_qmod_field_type(parent_name, var)
|
334
|
+
for dim in reversed(dimensions):
|
335
|
+
qmod_type = QArray[qmod_type, dim] # type:ignore[valid-type]
|
336
|
+
fields[parent_name] = qmod_type
|
337
|
+
|
338
|
+
|
339
|
+
def _get_qmod_field_type(var_name: str, var_data: _GeneralVarData) -> type[QVar]:
|
340
|
+
if var_data.domain not in SUPPORTED_TYPES:
|
341
|
+
raise ClassiqValueError(
|
342
|
+
f"Type {str(var_data.domain)!r} of variable {var_name!r} is not supported"
|
343
|
+
)
|
344
|
+
|
345
|
+
if var_data.domain == pyo.Binary:
|
346
|
+
return QBit
|
347
|
+
|
348
|
+
bounds = var_data.bounds
|
349
|
+
if bounds is None:
|
350
|
+
raise ClassiqValueError(f"Variable {var_name!r} has no bounds")
|
351
|
+
lb, ub = bounds
|
352
|
+
if not isinstance(lb, int) or not isinstance(ub, int):
|
353
|
+
raise ClassiqValueError(
|
354
|
+
f"Non-integer bounds for variable {var_name!r} are not supported"
|
355
|
+
)
|
356
|
+
qnum: Any = QNum # mypy shenanigans
|
357
|
+
return qnum[math.ceil(math.log2(ub - lb + 1)), False, 0]
|
358
|
+
|
359
|
+
|
360
|
+
def evaluate_objective(
|
361
|
+
var_mapping: dict[Any, Union[str, tuple[str, tuple[int, ...]]]],
|
362
|
+
sympy_expr: sympy.Expr,
|
363
|
+
struct_obj: Any,
|
364
|
+
) -> Any:
|
365
|
+
sympy_assignment = {
|
366
|
+
sympy_var: (
|
367
|
+
getattr(struct_obj, field_accessor)
|
368
|
+
if isinstance(field_accessor, str)
|
369
|
+
else _get_item(getattr(struct_obj, field_accessor[0]), field_accessor[1])
|
370
|
+
)
|
371
|
+
for sympy_var, field_accessor in var_mapping.items()
|
372
|
+
}
|
373
|
+
|
374
|
+
# classical objective evaluation
|
375
|
+
if not isinstance(struct_obj, QStruct):
|
376
|
+
return float(sympy_expr.evalf(subs=sympy_assignment))
|
377
|
+
|
378
|
+
# quantum objective evaluation
|
379
|
+
expr_str = str(sympy_expr).replace("'", "")
|
380
|
+
for var_name, var_value in sympy_assignment.items():
|
381
|
+
var_name = str(var_name).replace("'", "")
|
382
|
+
expr_str = re.sub(rf"\b{var_name}\b", str(var_value), expr_str)
|
383
|
+
return SymbolicExpr(expr=expr_str, is_quantum=True)
|
384
|
+
|
385
|
+
|
386
|
+
def _get_item(obj: Any, multi_index: tuple[int, ...]) -> Any:
|
387
|
+
for idx in multi_index:
|
388
|
+
obj = obj[idx]
|
389
|
+
return obj
|
390
|
+
|
391
|
+
|
392
|
+
def get_field_name(var: _GeneralVarData) -> str:
|
393
|
+
return var.local_name.replace("[", "_").replace("]", "").replace(",", "_")
|
394
|
+
|
395
|
+
|
396
|
+
def is_index_var(var: _GeneralVarData) -> bool:
|
397
|
+
index = var.index()
|
398
|
+
return isinstance(index, int) or (
|
399
|
+
isinstance(index, tuple) and all(isinstance(idx, int) for idx in index)
|
400
|
+
)
|
401
|
+
|
402
|
+
|
403
|
+
def index_as_tuple(index: Union[int, tuple[int, ...]]) -> tuple[int, ...]:
|
404
|
+
if isinstance(index, int):
|
405
|
+
return (index,)
|
406
|
+
return index
|
407
|
+
|
408
|
+
|
409
|
+
@contextmanager
|
410
|
+
def add_var_domain_constraints(model: ConcreteModel) -> Iterator[None]:
|
411
|
+
vars = extract(model, _GeneralVarData)
|
412
|
+
constraints = [
|
413
|
+
constraint
|
414
|
+
for var in vars
|
415
|
+
if (constraint := _get_var_domain_constraint(var)) is not None
|
416
|
+
]
|
417
|
+
if len(constraints) == 0:
|
418
|
+
yield
|
419
|
+
return
|
420
|
+
model.var_domain_constraints = pyo.ConstraintList()
|
421
|
+
for constraint in constraints:
|
422
|
+
model.var_domain_constraints.add(constraint)
|
423
|
+
yield
|
424
|
+
model.del_component("var_domain_constraints")
|
425
|
+
|
426
|
+
|
427
|
+
def _get_var_domain_constraint(var: _GeneralVarData) -> Optional[ExpressionBase]:
|
428
|
+
bounds = var.bounds
|
429
|
+
if (
|
430
|
+
type(bounds) is not tuple
|
431
|
+
or len(bounds) != 2
|
432
|
+
or not all(isinstance(bounds[idx], int) for idx in (0, 1))
|
433
|
+
):
|
434
|
+
raise ClassiqValueError(
|
435
|
+
f"Missing bounds for variable {var.local_name}. Expected both lower and "
|
436
|
+
f"upper bounds, got {bounds}"
|
437
|
+
)
|
438
|
+
lb, ub = bounds
|
439
|
+
if ub < lb:
|
440
|
+
raise ClassiqValueError(
|
441
|
+
f"Illegal bounds for variable {var.local_name}. The upper bound ({ub}) is "
|
442
|
+
f"lesser than the lower bound ({lb})"
|
443
|
+
)
|
444
|
+
ub_norm = ub - lb + 1
|
445
|
+
if ub_norm & (ub_norm - 1) == 0:
|
446
|
+
return None
|
447
|
+
return var <= ub
|
classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import Optional
|
2
2
|
|
3
3
|
import pyomo.core as pyo
|
4
4
|
from pyomo.core.base import _GeneralVarData
|
@@ -6,7 +6,7 @@ from pyomo.core.expr.sympy_tools import Pyomo2SympyVisitor, PyomoSympyBimap
|
|
6
6
|
from sympy import Expr
|
7
7
|
|
8
8
|
|
9
|
-
def sympyify_vars(variables:
|
9
|
+
def sympyify_vars(variables: list[_GeneralVarData]) -> PyomoSympyBimap:
|
10
10
|
symbols_map = PyomoSympyBimap()
|
11
11
|
for var in variables:
|
12
12
|
Pyomo2SympyVisitor(symbols_map).walk_expression(var)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import copy
|
2
2
|
from itertools import chain, product
|
3
|
-
from typing import Callable,
|
3
|
+
from typing import Callable, Union
|
4
4
|
|
5
5
|
import pyomo.environ as pyo
|
6
6
|
from pyomo.core.base import _GeneralVarData
|
@@ -9,18 +9,11 @@ from pyomo.core.expr.relational_expr import EqualityExpression
|
|
9
9
|
|
10
10
|
from classiq.interface.combinatorial_optimization.encoding_types import EncodingType
|
11
11
|
from classiq.interface.combinatorial_optimization.solver_types import QSolver
|
12
|
+
from classiq.interface.exceptions import ClassiqCombOptInvalidEncodingTypeError
|
12
13
|
|
13
|
-
from classiq.
|
14
|
-
|
15
|
-
|
16
|
-
)
|
17
|
-
from classiq.applications_model_constructors.combinatorial_helpers.encoding_mapping import (
|
18
|
-
EncodingMapping,
|
19
|
-
)
|
20
|
-
from classiq.applications_model_constructors.combinatorial_helpers.encoding_utils import (
|
21
|
-
ONE_HOT_SUFFIX,
|
22
|
-
)
|
23
|
-
from classiq.exceptions import ClassiqCombOptInvalidEncodingTypeError
|
14
|
+
from classiq.applications.combinatorial_helpers import encoding_utils, pyomo_utils
|
15
|
+
from classiq.applications.combinatorial_helpers.encoding_mapping import EncodingMapping
|
16
|
+
from classiq.applications.combinatorial_helpers.encoding_utils import ONE_HOT_SUFFIX
|
24
17
|
|
25
18
|
|
26
19
|
def _make_invalid_encoding_type_error(
|
@@ -68,7 +61,7 @@ class ModelEncoder:
|
|
68
61
|
self._encode_objective()
|
69
62
|
|
70
63
|
@property
|
71
|
-
def _shift_substitution_dict(self) ->
|
64
|
+
def _shift_substitution_dict(self) -> dict[int, pyo.Expression]:
|
72
65
|
variables = pyomo_utils.extract(self.encoded_model, pyo.Var)
|
73
66
|
return {id(var): var + var.lb for var in variables}
|
74
67
|
|
@@ -92,7 +85,9 @@ class ModelEncoder:
|
|
92
85
|
encoding_expr = self._get_encoding_expr(var_data, encoding_vars)
|
93
86
|
|
94
87
|
self._add_expr_constraint(
|
95
|
-
constraint_name=var_data.name
|
88
|
+
constraint_name=var_data.name
|
89
|
+
+ encoding_utils.ENCODED_SUFFIX
|
90
|
+
+ encoding_utils.CONSTRAINT_SUFFIX,
|
96
91
|
expr=EqualityExpression(args=[var_data, encoding_expr]),
|
97
92
|
)
|
98
93
|
|
@@ -104,7 +99,7 @@ class ModelEncoder:
|
|
104
99
|
return vars_encoding_mapping
|
105
100
|
|
106
101
|
def _get_encoding_expr(
|
107
|
-
self, var_data: _GeneralVarData, encoding_vars:
|
102
|
+
self, var_data: _GeneralVarData, encoding_vars: list[_GeneralVarData]
|
108
103
|
) -> pyo.Expression:
|
109
104
|
if self.encoding_type == EncodingType.BINARY:
|
110
105
|
var_span = encoding_utils.get_var_span(var_data)
|
@@ -124,8 +119,8 @@ class ModelEncoder:
|
|
124
119
|
return encoding_expr
|
125
120
|
|
126
121
|
def _get_binary_coeffs(
|
127
|
-
self, encoding_vars:
|
128
|
-
) ->
|
122
|
+
self, encoding_vars: list[_GeneralVarData], var_span: int
|
123
|
+
) -> list[int]:
|
129
124
|
num_vars = len(encoding_vars)
|
130
125
|
if self.qsolver == QSolver.QAOAMixer:
|
131
126
|
return [2**idx for idx in range(num_vars)]
|
@@ -135,7 +130,7 @@ class ModelEncoder:
|
|
135
130
|
coeffs += [var_span - sum(coeffs)]
|
136
131
|
return coeffs
|
137
132
|
|
138
|
-
def _get_encoding_idxs(self, variable: pyo.Var) ->
|
133
|
+
def _get_encoding_idxs(self, variable: pyo.Var) -> list[tuple[int, int]]:
|
139
134
|
return list(
|
140
135
|
chain(
|
141
136
|
*[
|
@@ -162,7 +157,7 @@ class ModelEncoder:
|
|
162
157
|
)
|
163
158
|
|
164
159
|
def _add_rule_constraint(
|
165
|
-
self, constraint_name: str, idxs:
|
160
|
+
self, constraint_name: str, idxs: list[int], rule: Callable
|
166
161
|
) -> None:
|
167
162
|
encoding_constraint = pyo.Constraint(idxs, rule=rule)
|
168
163
|
|
@@ -179,7 +174,7 @@ class ModelEncoder:
|
|
179
174
|
def encode_expr(
|
180
175
|
self,
|
181
176
|
expr: pyo.Expression,
|
182
|
-
substitution_dict: Union[
|
177
|
+
substitution_dict: Union[dict[int, pyo.Expression], None] = None,
|
183
178
|
) -> pyo.Expression:
|
184
179
|
if substitution_dict is None:
|
185
180
|
substitution_dict = self.vars_encoding_mapping.substitution_dict
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import copy
|
2
|
-
from typing import
|
2
|
+
from typing import Union
|
3
3
|
|
4
4
|
from pyomo.core import ConcreteModel, Var
|
5
5
|
from pyomo.core.base.constraint import _GeneralConstraintData
|
@@ -7,25 +7,24 @@ from pyomo.core.expr.relational_expr import EqualityExpression
|
|
7
7
|
from pyomo.core.expr.visitor import identify_variables
|
8
8
|
from pyomo.repn.standard_repn import _GeneralVarData
|
9
9
|
|
10
|
-
from classiq.
|
10
|
+
from classiq.interface.exceptions import (
|
11
|
+
ClassiqCombOptNoSolutionError,
|
12
|
+
ClassiqCombOptTrivialProblemError,
|
13
|
+
)
|
14
|
+
|
15
|
+
from classiq.applications.combinatorial_helpers import (
|
11
16
|
encoding_utils,
|
12
17
|
pyomo_utils,
|
13
18
|
sympy_utils,
|
14
19
|
)
|
15
|
-
from classiq.
|
16
|
-
|
17
|
-
)
|
18
|
-
from classiq.applications_model_constructors.combinatorial_helpers.encoding_utils import (
|
20
|
+
from classiq.applications.combinatorial_helpers.arithmetic.isolation import isolate
|
21
|
+
from classiq.applications.combinatorial_helpers.encoding_utils import (
|
19
22
|
deal_with_trivial_boolean_constraint,
|
20
23
|
)
|
21
|
-
from classiq.
|
24
|
+
from classiq.applications.combinatorial_helpers.sympy_utils import (
|
22
25
|
sympyify_expression,
|
23
26
|
sympyify_vars,
|
24
27
|
)
|
25
|
-
from classiq.exceptions import (
|
26
|
-
ClassiqCombOptNoSolutionError,
|
27
|
-
ClassiqCombOptTrivialProblemError,
|
28
|
-
)
|
29
28
|
|
30
29
|
|
31
30
|
def remove_fixed_variables(model: ConcreteModel) -> ConcreteModel:
|
@@ -75,14 +74,14 @@ def _change_fixing_constraints_to_fixed_value(model: ConcreteModel) -> None:
|
|
75
74
|
pyomo_utils.delete_component(model, constraint)
|
76
75
|
|
77
76
|
|
78
|
-
def _get_fixing_constraints(model: ConcreteModel) ->
|
77
|
+
def _get_fixing_constraints(model: ConcreteModel) -> list[_GeneralConstraintData]:
|
79
78
|
constraints = pyomo_utils.extract(model, _GeneralConstraintData)
|
80
79
|
return list(filter(_is_fixing_constraint, constraints))
|
81
80
|
|
82
81
|
|
83
82
|
def _get_var_and_value_from_fixing_constraint(
|
84
83
|
constraint: _GeneralConstraintData,
|
85
|
-
) ->
|
84
|
+
) -> tuple[_GeneralVarData, float]:
|
86
85
|
var = next(identify_variables(constraint.body))
|
87
86
|
|
88
87
|
if isinstance(constraint.body, _GeneralVarData):
|
@@ -111,8 +110,8 @@ def _remove_empty_constraints(model: ConcreteModel) -> None:
|
|
111
110
|
|
112
111
|
|
113
112
|
def add_fixed_variables_to_solution(
|
114
|
-
original_model: ConcreteModel, solution:
|
115
|
-
) ->
|
113
|
+
original_model: ConcreteModel, solution: list[int]
|
114
|
+
) -> list[int]:
|
116
115
|
variables = pyomo_utils.extract(original_model, Var)
|
117
116
|
solution_iter = iter(solution)
|
118
117
|
# var.value might be 0 as well
|
@@ -1,29 +1,25 @@
|
|
1
|
-
from typing import List
|
2
|
-
|
3
1
|
import pyomo
|
4
2
|
import sympy as sp
|
5
3
|
from pyomo.core.base import _GeneralVarData
|
6
4
|
|
7
5
|
from classiq.interface.chemistry.operator import PauliOperator
|
6
|
+
from classiq.interface.exceptions import ClassiqCombOptNotSupportedProblemError
|
8
7
|
from classiq.interface.helpers import custom_pydantic_types
|
9
8
|
|
10
|
-
from classiq.
|
11
|
-
from classiq.
|
12
|
-
|
13
|
-
)
|
14
|
-
from classiq.applications_model_constructors.combinatorial_helpers.sympy_utils import (
|
9
|
+
from classiq.applications.combinatorial_helpers import memory
|
10
|
+
from classiq.applications.combinatorial_helpers.memory import InternalQuantumReg
|
11
|
+
from classiq.applications.combinatorial_helpers.sympy_utils import (
|
15
12
|
sympyify_expression,
|
16
13
|
sympyify_vars,
|
17
14
|
)
|
18
|
-
from classiq.exceptions import ClassiqCombOptNotSupportedProblemError
|
19
15
|
|
20
16
|
PYOMO_PARSING_ERROR_MESAGE = "Parsing of this pyomo model is not supported."
|
21
17
|
|
22
18
|
|
23
19
|
def convert_pyomo_to_hamiltonian(
|
24
20
|
pyomo_expr: pyomo.core.Expression,
|
25
|
-
ordered_pyomo_vars:
|
26
|
-
qregs:
|
21
|
+
ordered_pyomo_vars: list[_GeneralVarData],
|
22
|
+
qregs: list[InternalQuantumReg],
|
27
23
|
) -> PauliOperator:
|
28
24
|
symbols_map = sympyify_vars(ordered_pyomo_vars)
|
29
25
|
sympy_expr = sympyify_expression(pyomo_expr, symbols_map)
|
@@ -43,7 +39,7 @@ def convert_pyomo_to_hamiltonian(
|
|
43
39
|
|
44
40
|
|
45
41
|
def _convert_ising_sympy_to_operator(
|
46
|
-
ising_expr: sp.Expr, ordered_sympy_vars:
|
42
|
+
ising_expr: sp.Expr, ordered_sympy_vars: list[sp.Symbol]
|
47
43
|
) -> custom_pydantic_types.PydanticPauliList:
|
48
44
|
pauli_op_list: custom_pydantic_types.PydanticPauliList = []
|
49
45
|
for expr_term in ising_expr.args:
|
@@ -89,7 +85,7 @@ def _to_ising_symbolic_objective_function(objective: sp.Expr) -> sp.Expr:
|
|
89
85
|
return sp.expand(objective_ising)
|
90
86
|
|
91
87
|
|
92
|
-
def _get_vars(expr_term: sp.AtomicExpr) ->
|
88
|
+
def _get_vars(expr_term: sp.AtomicExpr) -> list[sp.Symbol]:
|
93
89
|
if isinstance(expr_term, sp.Symbol):
|
94
90
|
return [expr_term]
|
95
91
|
else:
|
@@ -97,8 +93,8 @@ def _get_vars(expr_term: sp.AtomicExpr) -> List[sp.Symbol]:
|
|
97
93
|
|
98
94
|
|
99
95
|
def _find_sub_list_items(
|
100
|
-
long_list:
|
101
|
-
) ->
|
96
|
+
long_list: list[sp.Symbol], sub_list: list[sp.Symbol]
|
97
|
+
) -> list[bool]:
|
102
98
|
return [x in sub_list for x in long_list]
|
103
99
|
|
104
100
|
|
@@ -113,7 +109,7 @@ def _get_coeff_from_expr(expr: sp.Expr) -> float:
|
|
113
109
|
|
114
110
|
|
115
111
|
def _add_auxiliary_qubits_to_operator(
|
116
|
-
operator: custom_pydantic_types.PydanticPauliList, qregs:
|
112
|
+
operator: custom_pydantic_types.PydanticPauliList, qregs: list[InternalQuantumReg]
|
117
113
|
) -> custom_pydantic_types.PydanticPauliList:
|
118
114
|
# TODO: handle the case when the auxiliary are in the middle of the circuit
|
119
115
|
for qreg in qregs:
|