classiq 0.38.0__py3-none-any.whl → 0.65.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/__init__.py +47 -32
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
- classiq/_internals/api_wrapper.py +235 -97
- classiq/_internals/async_utils.py +1 -3
- classiq/_internals/authentication/auth0.py +26 -10
- classiq/_internals/authentication/authentication.py +11 -0
- classiq/_internals/authentication/device.py +10 -5
- classiq/_internals/authentication/password_manager.py +18 -6
- classiq/_internals/authentication/token_manager.py +10 -5
- classiq/_internals/client.py +94 -33
- classiq/_internals/config.py +3 -4
- classiq/_internals/host_checker.py +38 -15
- classiq/_internals/jobs.py +60 -57
- classiq/_internals/type_validation.py +9 -9
- classiq/analyzer/__init__.py +1 -3
- classiq/analyzer/analyzer.py +24 -19
- classiq/analyzer/analyzer_utilities.py +10 -10
- classiq/analyzer/rb.py +15 -15
- classiq/analyzer/show_interactive_hack.py +27 -4
- classiq/analyzer/url_utils.py +2 -3
- classiq/applications/__init__.py +3 -12
- classiq/applications/chemistry/__init__.py +14 -10
- classiq/applications/chemistry/ansatz_parameters.py +4 -4
- classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +165 -158
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +4 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +1 -1
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +51 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +12 -12
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +8 -6
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +7 -11
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +67 -40
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +46 -0
- classiq/applications/combinatorial_helpers/pyomo_utils.py +447 -0
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +2 -2
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +15 -20
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +14 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +11 -15
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +1 -2
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +2 -3
- classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +5 -8
- classiq/applications/combinatorial_optimization/__init__.py +20 -6
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
- classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +35 -33
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +229 -0
- classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
- classiq/applications/finance/__init__.py +4 -5
- classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +48 -42
- classiq/applications/grover/__init__.py +9 -0
- classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +52 -51
- classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
- classiq/applications/libraries/qmci_library.py +22 -0
- classiq/applications/qnn/__init__.py +2 -4
- classiq/applications/qnn/circuit_utils.py +6 -6
- classiq/applications/qnn/datasets/__init__.py +9 -11
- classiq/applications/qnn/datasets/dataset_base_classes.py +7 -5
- classiq/applications/qnn/datasets/dataset_not.py +2 -1
- classiq/applications/qnn/datasets/dataset_parity.py +2 -2
- classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
- classiq/applications/qnn/qlayer.py +30 -10
- classiq/applications/qnn/torch_utils.py +4 -3
- classiq/applications/qnn/types.py +5 -5
- classiq/applications/qsvm/__init__.py +6 -4
- classiq/applications/qsvm/qsvm.py +3 -6
- classiq/applications/qsvm/qsvm_data_generation.py +3 -3
- classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +30 -28
- classiq/execution/__init__.py +8 -3
- classiq/execution/all_hardware_devices.py +11 -0
- classiq/execution/execution_session.py +400 -0
- classiq/execution/iqcc.py +63 -0
- classiq/execution/jobs.py +197 -25
- classiq/execution/qnn.py +79 -0
- classiq/executor.py +20 -115
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +43 -13
- classiq/interface/analyzer/cytoscape_graph.py +15 -9
- classiq/interface/analyzer/result.py +28 -32
- classiq/interface/applications/qsvm.py +20 -29
- classiq/interface/ast_node.py +16 -0
- classiq/interface/backend/backend_preferences.py +390 -121
- classiq/interface/backend/ionq/ionq_quantum_program.py +15 -23
- classiq/interface/backend/pydantic_backend.py +25 -22
- classiq/interface/backend/quantum_backend_providers.py +69 -16
- classiq/interface/chemistry/fermionic_operator.py +30 -21
- classiq/interface/chemistry/ground_state_problem.py +28 -25
- classiq/interface/chemistry/molecule.py +14 -10
- classiq/interface/chemistry/operator.py +64 -231
- classiq/interface/combinatorial_optimization/encoding_types.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
- classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
- classiq/interface/combinatorial_optimization/examples/mht.py +10 -6
- classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
- classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +8 -9
- classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
- classiq/interface/combinatorial_optimization/result.py +1 -3
- classiq/interface/combinatorial_optimization/solver_types.py +1 -1
- classiq/interface/debug_info/debug_info.py +86 -0
- classiq/{exceptions.py → interface/exceptions.py} +37 -9
- classiq/interface/execution/iqcc.py +19 -0
- classiq/interface/execution/jobs.py +15 -12
- classiq/interface/execution/primitives.py +18 -0
- classiq/interface/executor/constants.py +1 -0
- classiq/interface/executor/execution_preferences.py +26 -114
- classiq/interface/executor/execution_request.py +24 -46
- classiq/interface/executor/execution_result.py +30 -8
- classiq/interface/executor/iqae_result.py +4 -6
- classiq/interface/executor/optimizer_preferences.py +17 -14
- classiq/interface/executor/quantum_code.py +28 -24
- classiq/interface/executor/quantum_instruction_set.py +2 -2
- classiq/interface/executor/register_initialization.py +11 -14
- classiq/interface/executor/result.py +83 -56
- classiq/interface/executor/vqe_result.py +10 -10
- classiq/interface/finance/function_input.py +35 -25
- classiq/interface/finance/gaussian_model_input.py +5 -5
- classiq/interface/finance/log_normal_model_input.py +4 -4
- classiq/interface/finance/model_input.py +4 -4
- classiq/interface/generator/adjacency.py +1 -3
- classiq/interface/generator/amplitude_loading.py +22 -12
- classiq/interface/generator/ansatz_library.py +5 -5
- classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
- classiq/interface/generator/application_apis/chemistry_declarations.py +27 -187
- classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +18 -21
- classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
- classiq/interface/generator/application_apis/finance_declarations.py +48 -69
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -70
- classiq/interface/generator/arith/argument_utils.py +46 -5
- classiq/interface/generator/arith/arithmetic.py +35 -16
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +6 -7
- classiq/interface/generator/arith/arithmetic_expression_abc.py +66 -25
- classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -11
- classiq/interface/generator/arith/arithmetic_expression_validator.py +47 -43
- classiq/interface/generator/arith/arithmetic_operations.py +14 -6
- classiq/interface/generator/arith/arithmetic_param_getters.py +7 -8
- classiq/interface/generator/arith/arithmetic_result_builder.py +21 -17
- classiq/interface/generator/arith/ast_node_rewrite.py +3 -2
- classiq/interface/generator/arith/binary_ops.py +218 -130
- classiq/interface/generator/arith/endianness.py +1 -1
- classiq/interface/generator/arith/extremum_operations.py +96 -25
- classiq/interface/generator/arith/logical_ops.py +14 -12
- classiq/interface/generator/arith/number_utils.py +12 -6
- classiq/interface/generator/arith/register_user_input.py +60 -37
- classiq/interface/generator/arith/unary_ops.py +49 -29
- classiq/interface/generator/arith/uncomputation_methods.py +1 -1
- classiq/interface/generator/builtin_api_builder.py +2 -9
- classiq/interface/generator/chemistry_function_params.py +3 -3
- classiq/interface/generator/circuit_code/circuit_code.py +7 -7
- classiq/interface/generator/circuit_code/types_and_constants.py +4 -7
- classiq/interface/generator/commuting_pauli_exponentiation.py +7 -7
- classiq/interface/generator/compiler_keywords.py +5 -1
- classiq/interface/generator/complex_type.py +13 -18
- classiq/interface/generator/constant.py +3 -4
- classiq/interface/generator/control_state.py +34 -29
- classiq/interface/generator/copy.py +47 -0
- classiq/interface/generator/custom_ansatz.py +2 -5
- classiq/interface/generator/distance.py +3 -5
- classiq/interface/generator/excitations.py +3 -2
- classiq/interface/generator/expressions/atomic_expression_functions.py +21 -5
- classiq/interface/generator/expressions/enums/__init__.py +0 -10
- classiq/interface/generator/expressions/enums/finance_functions.py +12 -22
- classiq/interface/generator/expressions/evaluated_expression.py +5 -5
- classiq/interface/generator/expressions/expression.py +26 -14
- classiq/interface/generator/expressions/expression_constants.py +9 -3
- classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +99 -0
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +34 -8
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +36 -0
- classiq/interface/generator/expressions/qmod_sized_proxy.py +30 -2
- classiq/interface/generator/expressions/qmod_struct_instance.py +14 -2
- classiq/interface/generator/expressions/sympy_supported_expressions.py +19 -11
- classiq/interface/generator/finance.py +2 -2
- classiq/interface/generator/function_param_library.py +6 -6
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -10
- classiq/interface/generator/function_params.py +36 -64
- classiq/interface/generator/functions/__init__.py +0 -22
- classiq/interface/generator/functions/builtins/internal_operators.py +16 -0
- classiq/interface/generator/functions/classical_function_declaration.py +18 -9
- classiq/interface/generator/functions/classical_type.py +47 -166
- classiq/interface/generator/functions/concrete_types.py +55 -0
- classiq/interface/generator/functions/function_declaration.py +13 -14
- classiq/interface/generator/functions/port_declaration.py +1 -13
- classiq/interface/generator/functions/qmod_python_interface.py +2 -1
- classiq/interface/generator/functions/type_name.py +90 -0
- classiq/interface/generator/generated_circuit_data.py +153 -20
- classiq/interface/generator/grover_diffuser.py +32 -25
- classiq/interface/generator/grover_operator.py +34 -25
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +4 -6
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +9 -9
- classiq/interface/generator/hardware/hardware_data.py +72 -34
- classiq/interface/generator/hardware_efficient_ansatz.py +20 -16
- classiq/interface/generator/hartree_fock.py +13 -5
- classiq/interface/generator/identity.py +10 -6
- classiq/interface/generator/linear_pauli_rotations.py +32 -20
- classiq/interface/generator/mcmt_method.py +1 -1
- classiq/interface/generator/mcu.py +17 -15
- classiq/interface/generator/mcx.py +24 -17
- classiq/interface/generator/model/__init__.py +2 -5
- classiq/interface/generator/model/constraints.py +26 -8
- classiq/interface/generator/model/model.py +27 -190
- classiq/interface/generator/model/preferences/preferences.py +115 -41
- classiq/{quantum_register.py → interface/generator/model/quantum_register.py} +14 -17
- classiq/interface/generator/oracles/arithmetic_oracle.py +2 -4
- classiq/interface/generator/oracles/custom_oracle.py +15 -13
- classiq/interface/generator/oracles/oracle_abc.py +7 -7
- classiq/interface/generator/partitioned_register.py +7 -7
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +45 -29
- classiq/interface/generator/preferences/optimization.py +1 -2
- classiq/interface/generator/qpe.py +41 -30
- classiq/interface/generator/qsvm.py +9 -10
- classiq/interface/generator/quantum_function_call.py +88 -73
- classiq/interface/generator/quantum_program.py +41 -24
- classiq/interface/generator/range_types.py +11 -12
- classiq/interface/generator/register_role.py +18 -6
- classiq/interface/generator/slice_parsing_utils.py +5 -5
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +30 -39
- classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
- classiq/interface/generator/standard_gates/standard_gates.py +3 -3
- classiq/interface/generator/standard_gates/u_gate.py +7 -10
- classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
- classiq/interface/generator/state_preparation/distributions.py +16 -15
- classiq/interface/generator/state_preparation/metrics.py +4 -7
- classiq/interface/generator/state_preparation/state_preparation.py +25 -20
- classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +20 -6
- classiq/interface/generator/transpiler_basis_gates.py +7 -3
- classiq/interface/generator/types/builtin_enum_declarations.py +178 -0
- classiq/interface/generator/types/compilation_metadata.py +6 -0
- classiq/interface/generator/types/enum_declaration.py +54 -0
- classiq/interface/generator/types/qstruct_declaration.py +18 -0
- classiq/interface/generator/types/struct_declaration.py +7 -11
- classiq/interface/generator/ucc.py +5 -4
- classiq/interface/generator/unitary_gate.py +5 -5
- classiq/interface/generator/user_defined_function_params.py +4 -1
- classiq/interface/generator/validations/flow_graph.py +7 -7
- classiq/interface/generator/validations/validator_functions.py +4 -4
- classiq/interface/generator/visitor.py +23 -16
- classiq/interface/hardware.py +29 -8
- classiq/interface/helpers/classproperty.py +8 -0
- classiq/interface/helpers/custom_encoders.py +2 -2
- classiq/interface/helpers/custom_pydantic_types.py +40 -50
- classiq/interface/helpers/datastructures.py +26 -0
- classiq/interface/helpers/hashable_mixin.py +3 -2
- classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
- classiq/interface/helpers/pydantic_model_helpers.py +7 -5
- classiq/interface/helpers/validation_helpers.py +3 -20
- classiq/interface/helpers/versioned_model.py +1 -4
- classiq/interface/ide/ide_data.py +16 -20
- classiq/interface/ide/visual_model.py +130 -0
- classiq/interface/interface_version.py +1 -0
- classiq/interface/jobs.py +29 -69
- classiq/interface/model/allocate.py +16 -0
- classiq/interface/model/bind_operation.py +32 -9
- classiq/interface/model/classical_if.py +15 -0
- classiq/interface/model/classical_parameter_declaration.py +33 -3
- classiq/interface/model/control.py +45 -0
- classiq/interface/model/handle_binding.py +298 -20
- classiq/interface/model/inplace_binary_operation.py +29 -24
- classiq/interface/model/invert.py +12 -0
- classiq/interface/model/model.py +69 -61
- classiq/interface/model/native_function_definition.py +17 -20
- classiq/interface/model/parameter.py +13 -0
- classiq/interface/model/phase_operation.py +11 -0
- classiq/interface/model/port_declaration.py +27 -9
- classiq/interface/model/power.py +14 -0
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +30 -18
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +51 -14
- classiq/interface/model/quantum_expressions/quantum_expression.py +12 -35
- classiq/interface/model/quantum_function_call.py +141 -343
- classiq/interface/model/quantum_function_declaration.py +190 -157
- classiq/interface/model/quantum_lambda_function.py +33 -32
- classiq/interface/model/quantum_statement.py +71 -12
- classiq/interface/model/quantum_type.py +177 -40
- classiq/interface/model/quantum_variable_declaration.py +3 -25
- classiq/interface/model/repeat.py +15 -0
- classiq/interface/model/statement_block.py +40 -14
- classiq/interface/model/validation_handle.py +13 -6
- classiq/interface/model/variable_declaration_statement.py +3 -1
- classiq/interface/model/within_apply_operation.py +7 -5
- classiq/interface/server/global_versions.py +6 -7
- classiq/interface/server/routes.py +17 -21
- classiq/interface/source_reference.py +59 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +253 -0
- classiq/model_expansions/capturing/__init__.py +0 -0
- classiq/model_expansions/capturing/captured_vars.py +435 -0
- classiq/model_expansions/capturing/mangling_utils.py +56 -0
- classiq/model_expansions/closure.py +171 -0
- classiq/model_expansions/debug_flag.py +3 -0
- classiq/model_expansions/evaluators/__init__.py +0 -0
- classiq/model_expansions/evaluators/arg_type_match.py +158 -0
- classiq/model_expansions/evaluators/argument_types.py +42 -0
- classiq/model_expansions/evaluators/classical_expression.py +36 -0
- classiq/model_expansions/evaluators/control.py +144 -0
- classiq/model_expansions/evaluators/parameter_types.py +226 -0
- classiq/model_expansions/evaluators/quantum_type_utils.py +239 -0
- classiq/model_expansions/evaluators/type_type_match.py +90 -0
- classiq/model_expansions/expression_evaluator.py +135 -0
- classiq/model_expansions/expression_renamer.py +76 -0
- classiq/model_expansions/function_builder.py +247 -0
- classiq/model_expansions/generative_functions.py +158 -0
- classiq/model_expansions/interpreters/__init__.py +0 -0
- classiq/model_expansions/interpreters/base_interpreter.py +263 -0
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
- classiq/model_expansions/model_tables.py +18 -0
- classiq/model_expansions/quantum_operations/__init__.py +9 -0
- classiq/model_expansions/quantum_operations/bind.py +60 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +266 -0
- classiq/model_expansions/quantum_operations/classicalif.py +53 -0
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
- classiq/model_expansions/quantum_operations/emitter.py +181 -0
- classiq/model_expansions/quantum_operations/quantum_function_call.py +33 -0
- classiq/model_expansions/quantum_operations/repeat.py +56 -0
- classiq/model_expansions/quantum_operations/shallow_emitter.py +180 -0
- classiq/model_expansions/quantum_operations/variable_decleration.py +28 -0
- classiq/model_expansions/scope.py +240 -0
- classiq/model_expansions/scope_initialization.py +150 -0
- classiq/model_expansions/sympy_conversion/__init__.py +0 -0
- classiq/model_expansions/sympy_conversion/arithmetics.py +49 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +179 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +123 -0
- classiq/model_expansions/transformers/__init__.py +0 -0
- classiq/model_expansions/transformers/ast_renamer.py +26 -0
- classiq/model_expansions/transformers/var_splitter.py +299 -0
- classiq/model_expansions/utils/__init__.py +0 -0
- classiq/model_expansions/utils/counted_name_allocator.py +11 -0
- classiq/model_expansions/utils/handles_collector.py +33 -0
- classiq/model_expansions/visitors/__init__.py +0 -0
- classiq/model_expansions/visitors/boolean_expression_transformers.py +214 -0
- classiq/model_expansions/visitors/variable_references.py +144 -0
- classiq/open_library/__init__.py +4 -0
- classiq/open_library/functions/__init__.py +130 -0
- classiq/open_library/functions/amplitude_estimation.py +30 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +181 -0
- classiq/open_library/functions/grover.py +157 -0
- classiq/open_library/functions/hea.py +115 -0
- classiq/open_library/functions/linear_pauli_rotation.py +82 -0
- classiq/open_library/functions/modular_exponentiation.py +201 -0
- classiq/open_library/functions/qaoa_penalty.py +117 -0
- classiq/open_library/functions/qft_functions.py +54 -0
- classiq/open_library/functions/qpe.py +46 -0
- classiq/open_library/functions/qsvt.py +331 -0
- classiq/open_library/functions/state_preparation.py +301 -0
- classiq/open_library/functions/swap_test.py +27 -0
- classiq/open_library/functions/utility_functions.py +81 -0
- classiq/open_library/functions/variational.py +52 -0
- classiq/qmod/__init__.py +10 -10
- classiq/qmod/builtins/__init__.py +19 -2
- classiq/qmod/builtins/classical_execution_primitives.py +36 -14
- classiq/qmod/builtins/classical_functions.py +39 -43
- classiq/qmod/builtins/constants.py +10 -0
- classiq/qmod/builtins/enums.py +208 -0
- classiq/qmod/builtins/functions/__init__.py +137 -0
- classiq/qmod/builtins/functions/allocation.py +150 -0
- classiq/qmod/builtins/functions/arithmetic.py +55 -0
- classiq/qmod/builtins/functions/benchmarking.py +8 -0
- classiq/qmod/builtins/functions/chemistry.py +91 -0
- classiq/qmod/builtins/functions/exponentiation.py +105 -0
- classiq/qmod/builtins/functions/finance.py +34 -0
- classiq/qmod/builtins/functions/operators.py +16 -0
- classiq/qmod/builtins/functions/qsvm.py +24 -0
- classiq/qmod/builtins/functions/standard_gates.py +651 -0
- classiq/qmod/builtins/operations.py +373 -40
- classiq/qmod/builtins/structs.py +103 -80
- classiq/qmod/cfunc.py +2 -2
- classiq/qmod/classical_function.py +4 -8
- classiq/qmod/cparam.py +64 -0
- classiq/qmod/create_model_function.py +56 -0
- classiq/qmod/declaration_inferrer.py +143 -101
- classiq/qmod/expression_query.py +20 -4
- classiq/qmod/generative.py +42 -0
- classiq/qmod/model_state_container.py +18 -6
- classiq/qmod/native/__init__.py +7 -0
- classiq/qmod/native/expression_to_qmod.py +16 -11
- classiq/qmod/native/pretty_printer.py +187 -97
- classiq/qmod/pretty_print/__init__.py +7 -0
- classiq/qmod/pretty_print/expression_to_python.py +222 -0
- classiq/qmod/pretty_print/pretty_printer.py +572 -0
- classiq/qmod/python_classical_type.py +67 -0
- classiq/qmod/qfunc.py +60 -8
- classiq/qmod/qmod_constant.py +93 -26
- classiq/qmod/qmod_parameter.py +68 -59
- classiq/qmod/qmod_variable.py +468 -155
- classiq/qmod/quantum_callable.py +17 -7
- classiq/qmod/quantum_expandable.py +269 -96
- classiq/qmod/quantum_function.py +196 -41
- classiq/qmod/semantics/__init__.py +0 -0
- classiq/qmod/semantics/annotation/__init__.py +0 -0
- classiq/qmod/semantics/annotation/call_annotation.py +92 -0
- classiq/qmod/semantics/annotation/qstruct_annotator.py +23 -0
- classiq/qmod/semantics/error_manager.py +88 -0
- classiq/qmod/semantics/lambdas.py +25 -0
- classiq/qmod/semantics/static_semantics_visitor.py +384 -0
- classiq/qmod/semantics/validation/__init__.py +0 -0
- classiq/qmod/semantics/validation/constants_validation.py +16 -0
- classiq/qmod/semantics/validation/func_call_validation.py +99 -0
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
- classiq/qmod/semantics/validation/handle_validation.py +85 -0
- classiq/qmod/semantics/validation/main_validation.py +33 -0
- classiq/qmod/semantics/validation/types_validation.py +128 -0
- classiq/qmod/symbolic.py +147 -123
- classiq/qmod/symbolic_expr.py +27 -12
- classiq/qmod/symbolic_type.py +2 -5
- classiq/qmod/type_attribute_remover.py +32 -0
- classiq/qmod/utilities.py +98 -4
- classiq/qmod/write_qmod.py +17 -3
- classiq/synthesis.py +210 -22
- {classiq-0.38.0.dist-info → classiq-0.65.3.dist-info}/METADATA +16 -9
- classiq-0.65.3.dist-info/RECORD +521 -0
- classiq/_internals/_qfunc_ext.py +0 -6
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -25
- classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -65
- classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +0 -243
- classiq/applications_model_constructors/libraries/ampltitude_estimation_library.py +0 -11
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
- classiq/builtin_functions/__init__.py +0 -43
- classiq/builtin_functions/amplitude_loading.py +0 -3
- classiq/builtin_functions/binary_ops.py +0 -1
- classiq/builtin_functions/exponentiation.py +0 -5
- classiq/builtin_functions/qpe.py +0 -4
- classiq/builtin_functions/qsvm.py +0 -7
- classiq/builtin_functions/range_types.py +0 -5
- classiq/builtin_functions/standard_gates.py +0 -1
- classiq/builtin_functions/state_preparation.py +0 -6
- classiq/builtin_functions/suzuki_trotter.py +0 -3
- classiq/interface/executor/aws_execution_cost.py +0 -73
- classiq/interface/executor/error_mitigation.py +0 -6
- classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
- classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
- classiq/interface/generator/expressions/enums/chemistry.py +0 -28
- classiq/interface/generator/expressions/enums/classical_enum.py +0 -5
- classiq/interface/generator/expressions/enums/ladder_operator.py +0 -16
- classiq/interface/generator/expressions/enums/optimizers.py +0 -9
- classiq/interface/generator/expressions/enums/pauli.py +0 -8
- classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +0 -641
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/exponentiation_functions.py +0 -89
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +0 -1229
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
- classiq/interface/generator/functions/foreign_function_definition.py +0 -114
- classiq/interface/generator/functions/function_implementation.py +0 -107
- classiq/interface/generator/functions/native_function_definition.py +0 -155
- classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
- classiq/interface/generator/functions/register.py +0 -44
- classiq/interface/generator/functions/register_mapping_data.py +0 -106
- classiq/interface/generator/inequality_mixer.py +0 -51
- classiq/interface/generator/model/classical_main_validator.py +0 -106
- classiq/interface/generator/range_mixer.py +0 -56
- classiq/interface/generator/state_propagator.py +0 -74
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
- classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +0 -22
- classiq/interface/ide/show.py +0 -34
- classiq/interface/model/call_synthesis_data.py +0 -68
- classiq/interface/model/common_model_types.py +0 -23
- classiq/interface/model/quantum_expressions/control_state.py +0 -38
- classiq/interface/model/quantum_if_operation.py +0 -94
- classiq/interface/model/resolvers/function_call_resolver.py +0 -43
- classiq/interface/model/validations/handle_validation_base.py +0 -55
- classiq/interface/model/validations/handles_validator.py +0 -156
- classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
- classiq/model/__init__.py +0 -14
- classiq/model/composite_function_generator.py +0 -33
- classiq/model/function_handler.py +0 -462
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -229
- classiq/qmod/builtins/functions.py +0 -913
- classiq/qmod/qmod_struct.py +0 -37
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -205
- classiq/quantum_functions/decorators.py +0 -22
- classiq/quantum_functions/function_library.py +0 -181
- classiq/quantum_functions/function_parser.py +0 -74
- classiq/quantum_functions/quantum_function.py +0 -236
- classiq-0.38.0.dist-info/RECORD +0 -454
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
- /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
- /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
- /classiq/{interface/generator/credit_risk_example → applications/hamiltonian}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
- /classiq/interface/{model/resolvers → debug_info}/__init__.py +0 -0
- /classiq/{_internals → interface}/enum_utils.py +0 -0
- /classiq/interface/{model/validations → generator/functions/builtins}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → model_expansions/__init__.py} +0 -0
- {classiq-0.38.0.dist-info → classiq-0.65.3.dist-info}/WHEEL +0 -0
@@ -0,0 +1,572 @@
|
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import Optional, Union, cast
|
3
|
+
|
4
|
+
import black
|
5
|
+
|
6
|
+
from classiq.interface.exceptions import ClassiqInternalError
|
7
|
+
from classiq.interface.generator.constant import Constant
|
8
|
+
from classiq.interface.generator.expressions.expression import Expression
|
9
|
+
from classiq.interface.generator.functions.classical_type import (
|
10
|
+
Bool,
|
11
|
+
ClassicalArray,
|
12
|
+
ClassicalList,
|
13
|
+
Integer,
|
14
|
+
Real,
|
15
|
+
)
|
16
|
+
from classiq.interface.generator.functions.concrete_types import (
|
17
|
+
ConcreteClassicalType,
|
18
|
+
ConcreteQuantumType,
|
19
|
+
)
|
20
|
+
from classiq.interface.generator.functions.port_declaration import (
|
21
|
+
PortDeclarationDirection,
|
22
|
+
)
|
23
|
+
from classiq.interface.generator.functions.type_name import TypeName
|
24
|
+
from classiq.interface.generator.types.enum_declaration import EnumDeclaration
|
25
|
+
from classiq.interface.generator.types.qstruct_declaration import QStructDeclaration
|
26
|
+
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
27
|
+
from classiq.interface.generator.visitor import NodeType, Visitor
|
28
|
+
from classiq.interface.model.allocate import Allocate
|
29
|
+
from classiq.interface.model.bind_operation import BindOperation
|
30
|
+
from classiq.interface.model.classical_if import ClassicalIf
|
31
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
32
|
+
AnonClassicalParameterDeclaration,
|
33
|
+
)
|
34
|
+
from classiq.interface.model.control import Control
|
35
|
+
from classiq.interface.model.handle_binding import (
|
36
|
+
FieldHandleBinding,
|
37
|
+
HandleBinding,
|
38
|
+
SlicedHandleBinding,
|
39
|
+
SubscriptHandleBinding,
|
40
|
+
)
|
41
|
+
from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperation
|
42
|
+
from classiq.interface.model.invert import Invert
|
43
|
+
from classiq.interface.model.model import Model
|
44
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
45
|
+
from classiq.interface.model.phase_operation import PhaseOperation
|
46
|
+
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
47
|
+
from classiq.interface.model.power import Power
|
48
|
+
from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
|
49
|
+
AmplitudeLoadingOperation,
|
50
|
+
)
|
51
|
+
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
52
|
+
ArithmeticOperation,
|
53
|
+
ArithmeticOperationKind,
|
54
|
+
)
|
55
|
+
from classiq.interface.model.quantum_function_call import (
|
56
|
+
QuantumFunctionCall,
|
57
|
+
)
|
58
|
+
from classiq.interface.model.quantum_function_declaration import (
|
59
|
+
AnonPositionalArg,
|
60
|
+
AnonQuantumOperandDeclaration,
|
61
|
+
QuantumFunctionDeclaration,
|
62
|
+
QuantumOperandDeclaration,
|
63
|
+
)
|
64
|
+
from classiq.interface.model.quantum_lambda_function import (
|
65
|
+
OperandIdentifier,
|
66
|
+
QuantumLambdaFunction,
|
67
|
+
)
|
68
|
+
from classiq.interface.model.quantum_type import (
|
69
|
+
QuantumBit,
|
70
|
+
QuantumBitvector,
|
71
|
+
QuantumNumeric,
|
72
|
+
)
|
73
|
+
from classiq.interface.model.quantum_variable_declaration import (
|
74
|
+
QuantumVariableDeclaration,
|
75
|
+
)
|
76
|
+
from classiq.interface.model.repeat import Repeat
|
77
|
+
from classiq.interface.model.statement_block import StatementBlock
|
78
|
+
from classiq.interface.model.variable_declaration_statement import (
|
79
|
+
VariableDeclarationStatement,
|
80
|
+
)
|
81
|
+
from classiq.interface.model.within_apply_operation import WithinApply
|
82
|
+
|
83
|
+
import classiq
|
84
|
+
from classiq.qmod.builtins.functions import BUILTIN_FUNCTION_DECLARATIONS
|
85
|
+
from classiq.qmod.pretty_print.expression_to_python import transform_expression
|
86
|
+
from classiq.qmod.utilities import DEFAULT_DECIMAL_PRECISION
|
87
|
+
|
88
|
+
|
89
|
+
class VariableDeclarationAssignment(Visitor):
|
90
|
+
def __init__(self, pretty_printer: "PythonPrettyPrinter") -> None:
|
91
|
+
self.pretty_printer = pretty_printer
|
92
|
+
|
93
|
+
def visit(self, node: NodeType) -> tuple[str, list[str]]:
|
94
|
+
res = super().visit(node)
|
95
|
+
if not isinstance(res, tuple):
|
96
|
+
raise AssertionError(f"Pretty printing for {type(node)} is not supported ")
|
97
|
+
return res # type: ignore[return-value]
|
98
|
+
|
99
|
+
def visit_QuantumBit(self, qtype: QuantumBit) -> tuple[str, list[str]]:
|
100
|
+
self.pretty_printer._imports["QBit"] = 1
|
101
|
+
return "QBit", []
|
102
|
+
|
103
|
+
def visit_QuantumBitvector(
|
104
|
+
self, qtype: QuantumBitvector
|
105
|
+
) -> tuple[str, Optional[list[str]]]:
|
106
|
+
self.pretty_printer._imports["QArray"] = 1
|
107
|
+
|
108
|
+
element_type = self.pretty_printer.visit(qtype.element_type)
|
109
|
+
if qtype.length is not None:
|
110
|
+
return "QArray", [element_type, self.pretty_printer.visit(qtype.length)]
|
111
|
+
return "QArray", [element_type]
|
112
|
+
|
113
|
+
def visit_QuantumNumeric(
|
114
|
+
self, qtype: QuantumNumeric
|
115
|
+
) -> tuple[str, Optional[list[str]]]:
|
116
|
+
self.pretty_printer._imports["QNum"] = 1
|
117
|
+
return "QNum", self.pretty_printer._get_qnum_properties(qtype)
|
118
|
+
|
119
|
+
def visit_TypeName(self, qtype: TypeName) -> tuple[str, list[str]]:
|
120
|
+
return qtype.name, []
|
121
|
+
|
122
|
+
|
123
|
+
class PythonPrettyPrinter(Visitor):
|
124
|
+
def __init__(self, decimal_precision: int = DEFAULT_DECIMAL_PRECISION) -> None:
|
125
|
+
self._level = 0
|
126
|
+
self._decimal_precision = decimal_precision
|
127
|
+
self._imports = {"qfunc": 1}
|
128
|
+
self._import_enum = False
|
129
|
+
self._import_dataclass = False
|
130
|
+
self._import_annotated = False
|
131
|
+
self._symbolic_imports: dict[str, int] = dict()
|
132
|
+
self._functions: Optional[Mapping[str, QuantumFunctionDeclaration]] = None
|
133
|
+
|
134
|
+
def visit(self, node: NodeType) -> str:
|
135
|
+
res = super().visit(node)
|
136
|
+
if not isinstance(res, str):
|
137
|
+
raise AssertionError(f"Pretty printing for {type(node)} is not supported ")
|
138
|
+
return res
|
139
|
+
|
140
|
+
def visit_Model(self, model: Model) -> str:
|
141
|
+
self._functions = {**model.function_dict, **BUILTIN_FUNCTION_DECLARATIONS}
|
142
|
+
enum_decls = [self.visit(decl) for decl in model.enums]
|
143
|
+
struct_decls = [self.visit(decl) for decl in model.types]
|
144
|
+
qstruct_decls = [self.visit(qstruct_decl) for qstruct_decl in model.qstructs]
|
145
|
+
func_defs = [self.visit(func) for func in model.functions]
|
146
|
+
constants = [self.visit(const) for const in model.constants]
|
147
|
+
classical_code = self.format_classical_code(model.classical_execution_code)
|
148
|
+
|
149
|
+
code = f"{self.format_imports()}\n\n{self.join_code_parts(*constants, *enum_decls, *struct_decls, *qstruct_decls, *func_defs, classical_code)}"
|
150
|
+
return black.format_str(code, mode=black.FileMode())
|
151
|
+
|
152
|
+
def format_classical_code(self, code: str) -> str:
|
153
|
+
if not code:
|
154
|
+
return ""
|
155
|
+
self._imports["cfunc"] = 1
|
156
|
+
self.check_execution_primitives(code)
|
157
|
+
formatted_code = code.replace("\n", "\n" + self._indent + " ")
|
158
|
+
return f"{self._indent}@cfunc\n{self._indent}def cmain() -> None:\n{self._indent} {formatted_code}"
|
159
|
+
|
160
|
+
def check_execution_primitives(self, code: str) -> None:
|
161
|
+
for primitive in dir(classiq.qmod.builtins.classical_execution_primitives):
|
162
|
+
if primitive + "(" in code:
|
163
|
+
self._imports[primitive] = 1
|
164
|
+
|
165
|
+
def format_imports(self) -> str:
|
166
|
+
imports = f"from classiq import {', '.join(self._imports.keys())}\n"
|
167
|
+
symbolic_imports = (
|
168
|
+
f"from classiq.qmod.symbolic import {', '.join(self._symbolic_imports.keys())}\n"
|
169
|
+
if self._symbolic_imports
|
170
|
+
else ""
|
171
|
+
)
|
172
|
+
return self.special_imports + imports + symbolic_imports
|
173
|
+
|
174
|
+
@property
|
175
|
+
def special_imports(self) -> str:
|
176
|
+
imports = ""
|
177
|
+
if self._import_annotated:
|
178
|
+
imports += "from typing import Annotated\n"
|
179
|
+
if self._import_dataclass:
|
180
|
+
imports += "from dataclasses import dataclass\n"
|
181
|
+
if self._import_enum:
|
182
|
+
imports += "from enum import IntEnum\n"
|
183
|
+
return imports
|
184
|
+
|
185
|
+
def join_code_parts(self, *code_parts: str) -> str:
|
186
|
+
return "\n".join(code_parts)
|
187
|
+
|
188
|
+
def visit_Constant(self, constant: Constant) -> str:
|
189
|
+
self._imports["QConstant"] = 1
|
190
|
+
constant_name = self.visit(constant.name)
|
191
|
+
return f'{self._indent}{constant_name} = QConstant("{constant_name}", {self.visit(constant.const_type)}, {self.visit(constant.value)})\n'
|
192
|
+
|
193
|
+
def _visit_arg_decls(self, func_def: QuantumFunctionDeclaration) -> str:
|
194
|
+
return ", ".join(
|
195
|
+
self.visit(arg_decl) for arg_decl in func_def.positional_arg_declarations
|
196
|
+
)
|
197
|
+
|
198
|
+
def visit_QuantumFunctionDeclaration(
|
199
|
+
self, func_decl: QuantumFunctionDeclaration
|
200
|
+
) -> str:
|
201
|
+
return (
|
202
|
+
f"@qfunc\ndef {func_decl.name}({self._visit_arg_decls(func_decl)}) -> None:"
|
203
|
+
)
|
204
|
+
|
205
|
+
def visit_EnumDeclaration(self, enum_decl: EnumDeclaration) -> str:
|
206
|
+
self._import_enum = True
|
207
|
+
return f"class {enum_decl.name}(IntEnum):\n{self._visit_members(enum_decl.members)}\n"
|
208
|
+
|
209
|
+
def _visit_members(self, members: dict[str, int]) -> str:
|
210
|
+
self._level += 1
|
211
|
+
members_str = "".join(
|
212
|
+
f"{self._indent}{self.visit(member_name)} = {member_value}\n"
|
213
|
+
for member_name, member_value in members.items()
|
214
|
+
)
|
215
|
+
self._level -= 1
|
216
|
+
return members_str
|
217
|
+
|
218
|
+
def visit_StructDeclaration(self, struct_decl: StructDeclaration) -> str:
|
219
|
+
self._import_dataclass = True
|
220
|
+
return f"@dataclass\nclass {struct_decl.name}:\n{self._visit_variables(struct_decl.variables)}\n"
|
221
|
+
|
222
|
+
def visit_QStructDeclaration(self, qstruct_decl: QStructDeclaration) -> str:
|
223
|
+
self._imports["QStruct"] = 1
|
224
|
+
return f"class {qstruct_decl.name}(QStruct):\n{self._visit_variables(qstruct_decl.fields)}\n"
|
225
|
+
|
226
|
+
def _visit_variables(
|
227
|
+
self, variables: Mapping[str, Union[ConcreteClassicalType, ConcreteQuantumType]]
|
228
|
+
) -> str:
|
229
|
+
self._level += 1
|
230
|
+
variables_str = "".join(
|
231
|
+
f"{self._indent}{self.visit(field_name)}: {self.visit(var_decl)};\n"
|
232
|
+
for field_name, var_decl in variables.items()
|
233
|
+
)
|
234
|
+
self._level -= 1
|
235
|
+
return variables_str
|
236
|
+
|
237
|
+
def visit_QuantumVariableDeclaration(
|
238
|
+
self, var_decl: QuantumVariableDeclaration
|
239
|
+
) -> str:
|
240
|
+
return f"{var_decl.name}: {self.visit(var_decl.quantum_type)}"
|
241
|
+
|
242
|
+
def visit_AnonPortDeclaration(self, port_decl: AnonPortDeclaration) -> str:
|
243
|
+
var = f"{port_decl.name}: {self.visit(port_decl.quantum_type)}"
|
244
|
+
var_name, var_type = var.split(": ")
|
245
|
+
for direction in PortDeclarationDirection:
|
246
|
+
if port_decl.direction == PortDeclarationDirection.Inout:
|
247
|
+
return var
|
248
|
+
if port_decl.direction == direction:
|
249
|
+
direction_identifier = direction.name
|
250
|
+
self._imports[direction_identifier] = 1
|
251
|
+
return f"{var_name}: {direction_identifier}[{var_type}]"
|
252
|
+
raise RuntimeError("Should not reach here")
|
253
|
+
|
254
|
+
def visit_QuantumBit(self, qtype: QuantumBit) -> str:
|
255
|
+
self._imports["QBit"] = 1
|
256
|
+
return "QBit"
|
257
|
+
|
258
|
+
def visit_QuantumBitvector(self, qtype: QuantumBitvector) -> str:
|
259
|
+
self._imports.update({"QArray": 1, "QBit": 1})
|
260
|
+
element_type = self.visit(qtype.element_type)
|
261
|
+
if qtype.length is not None:
|
262
|
+
return f"QArray[{element_type}, {_add_quotes(self.visit(qtype.length))}]"
|
263
|
+
return f"QArray[{element_type}]"
|
264
|
+
|
265
|
+
def visit_QuantumNumeric(self, qtype: QuantumNumeric) -> str:
|
266
|
+
self._imports["QNum"] = 1
|
267
|
+
params = ""
|
268
|
+
qnum_properties = self._get_qnum_properties(qtype)
|
269
|
+
if len(qnum_properties) > 0:
|
270
|
+
params = "[{}]".format(
|
271
|
+
", ".join(_add_quotes(param) for param in qnum_properties)
|
272
|
+
)
|
273
|
+
return f"QNum{params}"
|
274
|
+
|
275
|
+
def _get_qnum_properties(self, qtype: QuantumNumeric) -> list[str]:
|
276
|
+
params: list[str] = []
|
277
|
+
if qtype.size is None:
|
278
|
+
return params
|
279
|
+
params.append(self.visit(qtype.size))
|
280
|
+
|
281
|
+
is_signed_expr = qtype.is_signed
|
282
|
+
fraction_digits_expr = qtype.fraction_digits
|
283
|
+
if is_signed_expr is None:
|
284
|
+
if fraction_digits_expr is not None:
|
285
|
+
raise ClassiqInternalError
|
286
|
+
return params
|
287
|
+
if fraction_digits_expr is None:
|
288
|
+
raise ClassiqInternalError
|
289
|
+
|
290
|
+
is_unsigned = (
|
291
|
+
is_signed_expr.is_evaluated() and not is_signed_expr.to_bool_value()
|
292
|
+
) or is_signed_expr.expr == "UNSIGNED"
|
293
|
+
is_integer = (
|
294
|
+
fraction_digits_expr.is_evaluated()
|
295
|
+
and fraction_digits_expr.to_int_value() == 0
|
296
|
+
)
|
297
|
+
if is_unsigned and is_integer:
|
298
|
+
return params
|
299
|
+
params.append(self.visit(is_signed_expr))
|
300
|
+
params.append(self.visit(fraction_digits_expr))
|
301
|
+
|
302
|
+
return params
|
303
|
+
|
304
|
+
def visit_AnonClassicalParameterDeclaration(
|
305
|
+
self, cparam: AnonClassicalParameterDeclaration
|
306
|
+
) -> str:
|
307
|
+
return f"{cparam.name}: {self.visit(cparam.classical_type)}"
|
308
|
+
|
309
|
+
def visit_Integer(self, ctint: Integer) -> str:
|
310
|
+
self._imports["CInt"] = 1
|
311
|
+
return "CInt"
|
312
|
+
|
313
|
+
def visit_Real(self, ctint: Real) -> str:
|
314
|
+
self._imports["CReal"] = 1
|
315
|
+
return "CReal"
|
316
|
+
|
317
|
+
def visit_Bool(self, ctbool: Bool) -> str:
|
318
|
+
self._imports["CBool"] = 1
|
319
|
+
return "CBool"
|
320
|
+
|
321
|
+
def visit_ClassicalList(self, ctlist: ClassicalList) -> str:
|
322
|
+
self._imports["CArray"] = 1
|
323
|
+
return f"CArray[{self.visit(ctlist.element_type)}]"
|
324
|
+
|
325
|
+
def visit_ClassicalArray(self, ctarray: ClassicalArray) -> str:
|
326
|
+
self._imports["CArray"] = 1
|
327
|
+
return f"CArray[{self.visit(ctarray.element_type)}, {ctarray.size}]"
|
328
|
+
|
329
|
+
def visit_TypeName(self, type_: TypeName) -> str:
|
330
|
+
self._import_type_name(type_)
|
331
|
+
return type_.name
|
332
|
+
|
333
|
+
def _import_type_name(self, type_: TypeName) -> None:
|
334
|
+
if type_.name in dir(classiq.qmod.builtins.enums) + dir(
|
335
|
+
classiq.qmod.builtins.structs
|
336
|
+
):
|
337
|
+
self._imports[type_.name] = 1
|
338
|
+
|
339
|
+
def visit_VariableDeclarationStatement(
|
340
|
+
self, local_decl: VariableDeclarationStatement
|
341
|
+
) -> str:
|
342
|
+
type_name, params = VariableDeclarationAssignment(self).visit(
|
343
|
+
local_decl.quantum_type
|
344
|
+
)
|
345
|
+
params = [f'"{local_decl.name}"'] + params
|
346
|
+
param_args = ", ".join(params)
|
347
|
+
return f"{self._indent}{self.visit_QuantumVariableDeclaration(local_decl)} = {type_name}({param_args})\n"
|
348
|
+
|
349
|
+
def _visit_operand_arg_decl(self, arg_decl: AnonPositionalArg) -> str:
|
350
|
+
if isinstance(arg_decl, AnonPortDeclaration):
|
351
|
+
type_str = self.visit(arg_decl.quantum_type)
|
352
|
+
elif isinstance(arg_decl, AnonClassicalParameterDeclaration):
|
353
|
+
type_str = self.visit(arg_decl.classical_type)
|
354
|
+
else:
|
355
|
+
type_str = self.visit_AnonQuantumOperandDeclaration(arg_decl, no_param=True)
|
356
|
+
if arg_decl.name is None:
|
357
|
+
return type_str
|
358
|
+
self._import_annotated = True
|
359
|
+
return f'Annotated[{type_str}, "{arg_decl.name}"]'
|
360
|
+
|
361
|
+
def visit_AnonQuantumOperandDeclaration(
|
362
|
+
self, op_decl: AnonQuantumOperandDeclaration, no_param: bool = False
|
363
|
+
) -> str:
|
364
|
+
qcallable_identifier = "QCallableList" if op_decl.is_list else "QCallable"
|
365
|
+
self._imports[qcallable_identifier] = 1
|
366
|
+
args = ", ".join(
|
367
|
+
self._visit_operand_arg_decl(arg_decl)
|
368
|
+
for arg_decl in op_decl.positional_arg_declarations
|
369
|
+
)
|
370
|
+
param_name = "" if no_param else f"{op_decl.name}: "
|
371
|
+
return f"{param_name}{qcallable_identifier}" + (f"[{args}]" if args else "")
|
372
|
+
|
373
|
+
def visit_QuantumOperandDeclaration(
|
374
|
+
self, op_decl: QuantumOperandDeclaration
|
375
|
+
) -> str:
|
376
|
+
return self.visit_AnonQuantumOperandDeclaration(op_decl)
|
377
|
+
|
378
|
+
def visit_NativeFunctionDefinition(self, func_def: NativeFunctionDefinition) -> str:
|
379
|
+
self._level += 1
|
380
|
+
if len(func_def.body) == 0:
|
381
|
+
body = " pass"
|
382
|
+
else:
|
383
|
+
body = "".join(self.visit(statement) for statement in func_def.body)
|
384
|
+
self._level -= 1
|
385
|
+
return f"{self.visit_QuantumFunctionDeclaration(func_def)} \n{body}\n"
|
386
|
+
|
387
|
+
def visit_QuantumFunctionCall(self, func_call: QuantumFunctionCall) -> str:
|
388
|
+
args = self._get_args(func_call)
|
389
|
+
if func_call.func_name in dir(classiq.qmod.builtins.functions):
|
390
|
+
self._imports[func_call.func_name] = 1
|
391
|
+
return f"{self._indent}{func_call.func_name}{f'[{self.visit(func_call.function.index)}]' if isinstance(func_call.function, OperandIdentifier) else ''}({args})\n"
|
392
|
+
|
393
|
+
def _get_args(self, func_call: QuantumFunctionCall) -> str:
|
394
|
+
if len(func_call.positional_args) > 2 and self._functions is not None:
|
395
|
+
func_decl = self._functions[func_call.func_name]
|
396
|
+
if all(
|
397
|
+
param.name is not None
|
398
|
+
for param in func_decl.positional_arg_declarations
|
399
|
+
):
|
400
|
+
return ", ".join(
|
401
|
+
f"{self.visit(cast(str, arg_decl.name))}={self.visit(arg)}"
|
402
|
+
for arg_decl, arg in zip(
|
403
|
+
func_decl.positional_arg_declarations,
|
404
|
+
func_call.positional_args,
|
405
|
+
)
|
406
|
+
)
|
407
|
+
return ", ".join(self.visit(arg) for arg in func_call.positional_args)
|
408
|
+
|
409
|
+
def visit_Allocate(self, allocate: Allocate) -> str:
|
410
|
+
if allocate.size is not None:
|
411
|
+
size = f"{self.visit(allocate.size)}, "
|
412
|
+
else:
|
413
|
+
size = ""
|
414
|
+
return f"{self._indent}allocate({size}{self.visit(allocate.target)})\n"
|
415
|
+
|
416
|
+
def visit_Control(self, op: Control) -> str:
|
417
|
+
self._imports["control"] = 1
|
418
|
+
control_else = (
|
419
|
+
f", {self._visit_body(op.else_block)}" if op.else_block is not None else ""
|
420
|
+
)
|
421
|
+
return f"{self._indent}control({self.visit(op.expression)}, {self._visit_body(op.body)}{control_else})\n"
|
422
|
+
|
423
|
+
def visit_PhaseOperation(self, op: PhaseOperation) -> str:
|
424
|
+
self._imports["phase"] = 1
|
425
|
+
theta = f", {self.visit(op.theta)}" if op.theta is not None else ""
|
426
|
+
return f"{self._indent}phase({self.visit(op.expression)}{theta})\n"
|
427
|
+
|
428
|
+
def visit_ClassicalIf(self, op: ClassicalIf) -> str:
|
429
|
+
self._imports["if_"] = 1
|
430
|
+
return f"{self._indent}if_(condition={self.visit(op.condition)}, then={self._visit_body(op.then)}, else_={self._visit_body(op.else_)})\n"
|
431
|
+
|
432
|
+
def visit_WithinApply(self, op: WithinApply) -> str:
|
433
|
+
self._imports["within_apply"] = 1
|
434
|
+
return f"{self._indent}within_apply({self._visit_body(op.compute)}, {self._visit_body(op.action)})\n"
|
435
|
+
|
436
|
+
def visit_Repeat(self, repeat: Repeat) -> str:
|
437
|
+
self._imports["repeat"] = 1
|
438
|
+
return f"{self._indent}repeat({self.visit(repeat.count)}, {self._visit_body(repeat.body, [repeat.iter_var])})\n"
|
439
|
+
|
440
|
+
def visit_Power(self, power: Power) -> str:
|
441
|
+
self._imports["power"] = 1
|
442
|
+
return f"{self._indent}power({self.visit(power.power)}, {self._visit_body(power.body)})\n"
|
443
|
+
|
444
|
+
def visit_Invert(self, invert: Invert) -> str:
|
445
|
+
self._imports["invert"] = 1
|
446
|
+
return f"{self._indent}invert({self._visit_body(invert.body)})\n"
|
447
|
+
|
448
|
+
def _visit_body(
|
449
|
+
self, body: StatementBlock, operand_arguments: Optional[list[str]] = None
|
450
|
+
) -> str:
|
451
|
+
if len(body) == 0:
|
452
|
+
return "lambda: []"
|
453
|
+
argument_string = (
|
454
|
+
(" " + ", ".join(operand_arguments)) if operand_arguments else ""
|
455
|
+
)
|
456
|
+
code = f"lambda{argument_string}: {'[' if len(body) > 1 else ''}\n"
|
457
|
+
self._level += 1
|
458
|
+
for i, statement in enumerate(body):
|
459
|
+
if isinstance(statement, VariableDeclarationStatement):
|
460
|
+
raise AssertionError(
|
461
|
+
"pretty printing variable declaration statements in quantum lambda function is unsupported."
|
462
|
+
)
|
463
|
+
if isinstance(statement, AmplitudeLoadingOperation):
|
464
|
+
code += self.visit_AmplitudeLoadingOperation(statement, in_lambda=True)
|
465
|
+
elif isinstance(statement, ArithmeticOperation):
|
466
|
+
code += self.visit_ArithmeticOperation(statement, in_lambda=True)
|
467
|
+
else:
|
468
|
+
code += self.visit(statement)
|
469
|
+
if i < len(body) - 1:
|
470
|
+
code += ","
|
471
|
+
self._level -= 1
|
472
|
+
return f"{code}{']' if len(body) > 1 else ''}"
|
473
|
+
|
474
|
+
def visit_InplaceBinaryOperation(self, op: InplaceBinaryOperation) -> str:
|
475
|
+
self._imports[op.operation.value] = 1
|
476
|
+
return f"{self._indent}{op.operation.value}({self.visit(op.value)}, {self.visit(op.target)})\n"
|
477
|
+
|
478
|
+
def visit_Expression(self, expr: Expression) -> str:
|
479
|
+
return transform_expression(
|
480
|
+
expr.expr,
|
481
|
+
level=self._level,
|
482
|
+
decimal_precision=self._decimal_precision,
|
483
|
+
imports=self._imports,
|
484
|
+
symbolic_imports=self._symbolic_imports,
|
485
|
+
)
|
486
|
+
|
487
|
+
def visit_QuantumLambdaFunction(self, qlambda: QuantumLambdaFunction) -> str:
|
488
|
+
return self._visit_body(qlambda.body, qlambda.pos_rename_params)
|
489
|
+
|
490
|
+
def visit_HandleBinding(self, var_ref: HandleBinding) -> str:
|
491
|
+
return var_ref.name
|
492
|
+
|
493
|
+
def visit_SlicedHandleBinding(self, var_ref: SlicedHandleBinding) -> str:
|
494
|
+
return f"{self.visit(var_ref.base_handle)}[{self.visit(var_ref.start)}:{self.visit(var_ref.end)}]"
|
495
|
+
|
496
|
+
def visit_SubscriptHandleBinding(self, var_ref: SubscriptHandleBinding) -> str:
|
497
|
+
return f"{self.visit(var_ref.base_handle)}[{self.visit(var_ref.index)}]"
|
498
|
+
|
499
|
+
def visit_FieldHandleBinding(self, var_ref: FieldHandleBinding) -> str:
|
500
|
+
return f"{self.visit(var_ref.base_handle)}.{self.visit(var_ref.field)}"
|
501
|
+
|
502
|
+
def visit_ArithmeticOperation(
|
503
|
+
self, arith_op: ArithmeticOperation, in_lambda: bool = False
|
504
|
+
) -> str:
|
505
|
+
if arith_op.operation_kind == ArithmeticOperationKind.Assignment:
|
506
|
+
op = "|="
|
507
|
+
func = "assign"
|
508
|
+
elif arith_op.operation_kind == ArithmeticOperationKind.InplaceXor:
|
509
|
+
op = "^="
|
510
|
+
func = "inplace_xor"
|
511
|
+
else:
|
512
|
+
op = "+="
|
513
|
+
func = "inplace_add"
|
514
|
+
if in_lambda:
|
515
|
+
self._imports[func] = 1
|
516
|
+
return f"{func}({self.visit(arith_op.expression)}, {self._indent}{self.visit(arith_op.result_var)})\n"
|
517
|
+
return f"{self._indent}{self.visit(arith_op.result_var)} {op} {self.visit(arith_op.expression)}\n"
|
518
|
+
|
519
|
+
def visit_AmplitudeLoadingOperation(
|
520
|
+
self, amplitude_loading_op: AmplitudeLoadingOperation, in_lambda: bool = False
|
521
|
+
) -> str:
|
522
|
+
if in_lambda:
|
523
|
+
self._imports["assign_amplitude"] = 1
|
524
|
+
return f"assign_amplitude({self.visit(amplitude_loading_op.expression)}, {self._indent}{self.visit(amplitude_loading_op.result_var)})\n"
|
525
|
+
return f"{self._indent}{self.visit(amplitude_loading_op.result_var)} *= {self.visit(amplitude_loading_op.expression)}\n"
|
526
|
+
|
527
|
+
def _print_bind_handles(self, handles: list[HandleBinding]) -> str:
|
528
|
+
if len(handles) == 1:
|
529
|
+
return self.visit(handles[0])
|
530
|
+
|
531
|
+
return "[" + ", ".join(self.visit(handle) for handle in handles) + "]"
|
532
|
+
|
533
|
+
def visit_BindOperation(self, bind_op: BindOperation) -> str:
|
534
|
+
self._imports["bind"] = 1
|
535
|
+
return f"{self._indent}bind({self._print_bind_handles(bind_op.in_handles)}, {self._print_bind_handles(bind_op.out_handles)})\n"
|
536
|
+
|
537
|
+
def visit_list(self, node: list) -> str:
|
538
|
+
return "[" + ", ".join(self.visit(elem) for elem in node) + "]"
|
539
|
+
|
540
|
+
def visit_OperandIdentifier(self, op: OperandIdentifier) -> str:
|
541
|
+
return str(op)
|
542
|
+
|
543
|
+
@property
|
544
|
+
def _indent(self) -> str:
|
545
|
+
return " " * self._level
|
546
|
+
|
547
|
+
|
548
|
+
def _add_quotes(exp: str) -> str:
|
549
|
+
if (
|
550
|
+
exp.lower() == "true"
|
551
|
+
or exp.lower() == "false"
|
552
|
+
or _convertible_to_number(exp)
|
553
|
+
or _is_constant(exp)
|
554
|
+
):
|
555
|
+
return exp
|
556
|
+
|
557
|
+
return f'"{exp}"'
|
558
|
+
|
559
|
+
|
560
|
+
def _convertible_to_number(exp: str) -> bool:
|
561
|
+
for number_type in [int, float]:
|
562
|
+
try:
|
563
|
+
number_type(exp)
|
564
|
+
except ValueError:
|
565
|
+
pass
|
566
|
+
else:
|
567
|
+
return True
|
568
|
+
return False
|
569
|
+
|
570
|
+
|
571
|
+
def _is_constant(exp: str) -> bool:
|
572
|
+
return exp in ("SIGNED", "UNSIGNED")
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import dataclasses
|
2
|
+
import inspect
|
3
|
+
from enum import EnumMeta
|
4
|
+
from typing import (
|
5
|
+
Optional,
|
6
|
+
get_args,
|
7
|
+
get_origin,
|
8
|
+
)
|
9
|
+
|
10
|
+
from classiq.interface.exceptions import ClassiqValueError
|
11
|
+
from classiq.interface.generator.functions.classical_type import (
|
12
|
+
Bool,
|
13
|
+
ClassicalArray,
|
14
|
+
ClassicalList,
|
15
|
+
Integer,
|
16
|
+
Real,
|
17
|
+
)
|
18
|
+
from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
|
19
|
+
from classiq.interface.generator.functions.type_name import Enum, Struct
|
20
|
+
|
21
|
+
from classiq.qmod.cparam import CArray, CBool, CInt, CReal
|
22
|
+
from classiq.qmod.qmod_variable import get_type_hint_expr
|
23
|
+
from classiq.qmod.utilities import version_portable_get_args
|
24
|
+
|
25
|
+
CARRAY_ERROR_MESSAGE = (
|
26
|
+
"CArray accepts one or two generic parameters in the form "
|
27
|
+
"`CArray[<element-type>]` or `CArray[<element-type>, <size>]`"
|
28
|
+
)
|
29
|
+
|
30
|
+
|
31
|
+
class PythonClassicalType:
|
32
|
+
def convert(self, py_type: type) -> Optional[ConcreteClassicalType]:
|
33
|
+
if py_type is int or py_type is CInt:
|
34
|
+
return Integer()
|
35
|
+
elif py_type in (float, complex) or py_type is CReal:
|
36
|
+
return Real()
|
37
|
+
elif py_type is bool or py_type is CBool:
|
38
|
+
return Bool()
|
39
|
+
elif get_origin(py_type) is list:
|
40
|
+
element_type = self.convert(get_args(py_type)[0])
|
41
|
+
if element_type is not None:
|
42
|
+
return ClassicalList(element_type=element_type)
|
43
|
+
elif get_origin(py_type) is CArray:
|
44
|
+
array_args = version_portable_get_args(py_type)
|
45
|
+
if len(array_args) == 1:
|
46
|
+
return ClassicalList(element_type=self.convert(array_args[0]))
|
47
|
+
elif len(array_args) == 2:
|
48
|
+
return ClassicalArray(
|
49
|
+
element_type=self.convert(array_args[0]),
|
50
|
+
size=get_type_hint_expr(array_args[1]),
|
51
|
+
)
|
52
|
+
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
53
|
+
elif inspect.isclass(py_type) and dataclasses.is_dataclass(py_type):
|
54
|
+
self.register_struct(py_type)
|
55
|
+
return Struct(name=py_type.__name__)
|
56
|
+
elif inspect.isclass(py_type) and isinstance(py_type, EnumMeta):
|
57
|
+
self.register_enum(py_type)
|
58
|
+
return Enum(name=py_type.__name__)
|
59
|
+
elif py_type in (CArray, list):
|
60
|
+
raise ClassiqValueError(CARRAY_ERROR_MESSAGE)
|
61
|
+
return None
|
62
|
+
|
63
|
+
def register_struct(self, py_type: type) -> None:
|
64
|
+
pass
|
65
|
+
|
66
|
+
def register_enum(self, py_type: EnumMeta) -> None:
|
67
|
+
pass
|