classiq 0.93.0__py3-none-any.whl → 0.99.0__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 +11 -19
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +7 -7
- classiq/_analyzer_extras/interactive_hardware.py +19 -12
- classiq/_internals/api_wrapper.py +31 -142
- classiq/_internals/async_utils.py +4 -7
- classiq/_internals/authentication/auth0.py +41 -15
- classiq/_internals/authentication/authorization_code.py +9 -0
- classiq/_internals/authentication/authorization_flow.py +41 -0
- classiq/_internals/authentication/device.py +33 -52
- classiq/_internals/authentication/hybrid_flow.py +19 -0
- classiq/_internals/authentication/password_manager.py +13 -13
- classiq/_internals/authentication/token_manager.py +9 -9
- classiq/_internals/client.py +17 -44
- classiq/_internals/config.py +19 -5
- classiq/_internals/help.py +1 -2
- classiq/_internals/host_checker.py +3 -3
- classiq/_internals/jobs.py +14 -14
- classiq/_internals/type_validation.py +3 -3
- classiq/analyzer/analyzer.py +18 -18
- classiq/analyzer/rb.py +17 -8
- classiq/analyzer/show_interactive_hack.py +1 -1
- classiq/applications/__init__.py +2 -2
- classiq/applications/chemistry/__init__.py +0 -30
- classiq/applications/chemistry/op_utils.py +4 -4
- classiq/applications/chemistry/problems.py +3 -3
- classiq/applications/chemistry/ucc.py +1 -2
- classiq/applications/chemistry/z2_symmetries.py +4 -4
- classiq/applications/combinatorial_helpers/allowed_constraints.py +1 -3
- classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +2 -1
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +2 -2
- classiq/applications/combinatorial_helpers/encoding_mapping.py +2 -3
- classiq/applications/combinatorial_helpers/encoding_utils.py +2 -2
- classiq/applications/combinatorial_helpers/optimization_model.py +3 -4
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +2 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +8 -8
- classiq/applications/combinatorial_helpers/sympy_utils.py +1 -3
- classiq/applications/combinatorial_helpers/transformations/encoding.py +3 -3
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +1 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -3
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +4 -6
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +15 -10
- classiq/applications/hamiltonian/pauli_decomposition.py +6 -4
- classiq/applications/iqae/iqae.py +14 -11
- classiq/applications/qnn/datasets/dataset_base_classes.py +6 -6
- classiq/applications/qnn/datasets/dataset_parity.py +6 -6
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
- classiq/applications/qnn/qlayer.py +9 -8
- classiq/applications/qnn/torch_utils.py +5 -6
- classiq/applications/qnn/types.py +2 -1
- classiq/applications/qsp/__init__.py +20 -2
- classiq/applications/qsp/qsp.py +238 -10
- classiq/applications/qsvm/qsvm_data_generation.py +1 -2
- classiq/evaluators/classical_expression.py +0 -4
- classiq/evaluators/parameter_types.py +10 -8
- classiq/evaluators/qmod_annotated_expression.py +31 -26
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +14 -14
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +2 -1
- classiq/evaluators/qmod_expression_visitors/sympy_wrappers.py +8 -8
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +4 -4
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +14 -4
- classiq/evaluators/qmod_node_evaluators/list_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +3 -3
- classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +9 -9
- classiq/evaluators/qmod_node_evaluators/utils.py +6 -6
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +9 -10
- classiq/evaluators/qmod_type_inference/quantum_type_inference.py +5 -5
- classiq/execution/__init__.py +0 -3
- classiq/execution/execution_session.py +28 -21
- classiq/execution/jobs.py +26 -26
- classiq/execution/qnn.py +1 -2
- classiq/execution/user_budgets.py +71 -37
- classiq/executor.py +1 -3
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +4 -4
- classiq/interface/analyzer/cytoscape_graph.py +3 -3
- classiq/interface/analyzer/result.py +4 -4
- classiq/interface/ast_node.py +3 -3
- classiq/interface/backend/backend_preferences.py +26 -50
- classiq/interface/backend/ionq/ionq_quantum_program.py +5 -5
- classiq/interface/backend/provider_config/__init__.py +0 -0
- classiq/interface/backend/provider_config/provider_config.py +8 -0
- classiq/interface/backend/provider_config/providers/__init__.py +0 -0
- classiq/interface/backend/provider_config/providers/alice_bob.py +47 -0
- classiq/interface/backend/provider_config/providers/aqt.py +16 -0
- classiq/interface/backend/provider_config/providers/azure.py +37 -0
- classiq/interface/backend/provider_config/providers/braket.py +39 -0
- classiq/interface/backend/provider_config/providers/ibm.py +26 -0
- classiq/interface/backend/provider_config/providers/ionq.py +22 -0
- classiq/interface/backend/quantum_backend_providers.py +20 -2
- classiq/interface/chemistry/ansatz_library.py +3 -5
- classiq/interface/chemistry/operator.py +3 -3
- classiq/interface/combinatorial_optimization/examples/knapsack.py +2 -4
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +1 -2
- classiq/interface/compression_utils.py +2 -3
- classiq/interface/debug_info/debug_info.py +8 -7
- classiq/interface/exceptions.py +6 -7
- classiq/interface/execution/primitives.py +6 -6
- classiq/interface/executor/estimate_cost.py +1 -1
- classiq/interface/executor/execution_preferences.py +3 -5
- classiq/interface/executor/execution_request.py +10 -10
- classiq/interface/executor/execution_result.py +1 -2
- classiq/interface/executor/quantum_code.py +8 -8
- classiq/interface/executor/result.py +28 -18
- classiq/interface/executor/user_budget.py +25 -17
- classiq/interface/executor/vqe_result.py +5 -6
- classiq/interface/generator/ansatz_library.py +6 -8
- classiq/interface/generator/application_apis/__init__.py +0 -3
- classiq/interface/generator/arith/arithmetic.py +2 -2
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +2 -3
- classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -5
- classiq/interface/generator/arith/arithmetic_expression_parser.py +11 -4
- classiq/interface/generator/arith/arithmetic_expression_validator.py +12 -15
- classiq/interface/generator/arith/arithmetic_operations.py +4 -6
- classiq/interface/generator/arith/arithmetic_param_getters.py +70 -107
- classiq/interface/generator/arith/arithmetic_result_builder.py +4 -4
- classiq/interface/generator/arith/ast_node_rewrite.py +8 -4
- classiq/interface/generator/arith/binary_ops.py +15 -40
- classiq/interface/generator/arith/logical_ops.py +2 -3
- classiq/interface/generator/arith/number_utils.py +2 -2
- classiq/interface/generator/arith/register_user_input.py +3 -3
- classiq/interface/generator/arith/unary_ops.py +2 -2
- classiq/interface/generator/circuit_code/circuit_code.py +8 -10
- classiq/interface/generator/circuit_code/types_and_constants.py +1 -1
- classiq/interface/generator/complex_type.py +2 -2
- classiq/interface/generator/copy.py +1 -3
- classiq/interface/generator/expressions/atomic_expression_functions.py +0 -5
- classiq/interface/generator/expressions/evaluated_expression.py +2 -3
- classiq/interface/generator/expressions/expression.py +2 -2
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -7
- classiq/interface/generator/function_param_list.py +0 -40
- classiq/interface/generator/function_params.py +5 -6
- classiq/interface/generator/functions/classical_function_declaration.py +2 -2
- classiq/interface/generator/functions/classical_type.py +3 -3
- classiq/interface/generator/functions/type_modifier.py +0 -15
- classiq/interface/generator/functions/type_name.py +2 -2
- classiq/interface/generator/generated_circuit_data.py +14 -18
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +2 -4
- classiq/interface/generator/hardware/hardware_data.py +8 -8
- classiq/interface/generator/hardware_efficient_ansatz.py +9 -9
- classiq/interface/generator/mcu.py +3 -3
- classiq/interface/generator/mcx.py +3 -3
- classiq/interface/generator/model/constraints.py +34 -5
- classiq/interface/generator/model/preferences/preferences.py +15 -21
- classiq/interface/generator/model/quantum_register.py +7 -10
- classiq/interface/generator/noise_properties.py +3 -7
- classiq/interface/generator/parameters.py +1 -1
- classiq/interface/generator/partitioned_register.py +1 -2
- classiq/interface/generator/preferences/qasm_to_qmod_params.py +11 -0
- classiq/interface/generator/quantum_function_call.py +9 -12
- classiq/interface/generator/quantum_program.py +10 -23
- classiq/interface/generator/range_types.py +3 -3
- classiq/interface/generator/slice_parsing_utils.py +4 -5
- classiq/interface/generator/standard_gates/standard_gates.py +2 -4
- classiq/interface/generator/synthesis_execution_parameter.py +1 -3
- classiq/interface/generator/synthesis_metadata/synthesis_duration.py +9 -0
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +2 -3
- classiq/interface/generator/transpiler_basis_gates.py +12 -4
- classiq/interface/generator/types/builtin_enum_declarations.py +0 -145
- classiq/interface/generator/types/compilation_metadata.py +12 -1
- classiq/interface/generator/types/enum_declaration.py +2 -1
- classiq/interface/generator/validations/flow_graph.py +3 -3
- classiq/interface/generator/visitor.py +10 -12
- classiq/interface/hardware.py +2 -3
- classiq/interface/helpers/classproperty.py +2 -2
- classiq/interface/helpers/custom_encoders.py +2 -1
- classiq/interface/helpers/custom_pydantic_types.py +1 -1
- classiq/interface/helpers/text_utils.py +1 -4
- classiq/interface/ide/visual_model.py +6 -5
- classiq/interface/interface_version.py +1 -1
- classiq/interface/jobs.py +3 -3
- classiq/interface/model/allocate.py +4 -4
- classiq/interface/model/block.py +6 -2
- classiq/interface/model/bounds.py +3 -3
- classiq/interface/model/classical_if.py +4 -0
- classiq/interface/model/control.py +8 -1
- classiq/interface/model/inplace_binary_operation.py +2 -2
- classiq/interface/model/invert.py +4 -0
- classiq/interface/model/model.py +4 -4
- classiq/interface/model/model_visitor.py +40 -1
- classiq/interface/model/parameter.py +1 -3
- classiq/interface/model/port_declaration.py +1 -1
- classiq/interface/model/power.py +4 -0
- classiq/interface/model/quantum_expressions/quantum_expression.py +1 -2
- classiq/interface/model/quantum_function_call.py +3 -6
- classiq/interface/model/quantum_function_declaration.py +1 -0
- classiq/interface/model/quantum_lambda_function.py +4 -4
- classiq/interface/model/quantum_statement.py +11 -4
- classiq/interface/model/quantum_type.py +14 -14
- classiq/interface/model/repeat.py +4 -0
- classiq/interface/model/skip_control.py +4 -0
- classiq/interface/model/validation_handle.py +2 -3
- classiq/interface/model/variable_declaration_statement.py +2 -2
- classiq/interface/model/within_apply_operation.py +4 -0
- classiq/interface/pretty_print/expression_to_qmod.py +3 -4
- classiq/interface/server/routes.py +0 -16
- classiq/interface/source_reference.py +3 -4
- classiq/model_expansions/arithmetic.py +11 -7
- classiq/model_expansions/arithmetic_compute_result_attrs.py +30 -27
- classiq/model_expansions/capturing/captured_vars.py +3 -3
- classiq/model_expansions/capturing/mangling_utils.py +1 -2
- classiq/model_expansions/closure.py +12 -11
- classiq/model_expansions/function_builder.py +14 -6
- classiq/model_expansions/generative_functions.py +7 -12
- classiq/model_expansions/interpreters/base_interpreter.py +3 -7
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
- classiq/model_expansions/interpreters/generative_interpreter.py +5 -3
- classiq/model_expansions/quantum_operations/allocate.py +4 -4
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +2 -4
- classiq/model_expansions/quantum_operations/call_emitter.py +31 -37
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +2 -2
- classiq/model_expansions/quantum_operations/emitter.py +3 -5
- classiq/model_expansions/quantum_operations/expression_evaluator.py +3 -3
- classiq/model_expansions/quantum_operations/skip_control_verifier.py +1 -2
- classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
- classiq/model_expansions/scope.py +7 -7
- classiq/model_expansions/scope_initialization.py +4 -0
- classiq/model_expansions/visitors/symbolic_param_inference.py +6 -6
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +328 -0
- classiq/model_expansions/visitors/variable_references.py +15 -14
- classiq/open_library/functions/__init__.py +28 -11
- classiq/open_library/functions/amplitude_loading.py +81 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
- classiq/open_library/functions/grover.py +8 -10
- classiq/open_library/functions/lcu.py +47 -18
- classiq/open_library/functions/modular_exponentiation.py +93 -8
- classiq/open_library/functions/qsvt.py +66 -79
- classiq/open_library/functions/qsvt_temp.py +536 -0
- classiq/open_library/functions/state_preparation.py +130 -27
- classiq/qmod/__init__.py +6 -4
- classiq/qmod/builtins/classical_execution_primitives.py +4 -23
- classiq/qmod/builtins/classical_functions.py +1 -42
- classiq/qmod/builtins/enums.py +15 -153
- classiq/qmod/builtins/functions/__init__.py +9 -18
- classiq/qmod/builtins/functions/allocation.py +25 -4
- classiq/qmod/builtins/functions/arithmetic.py +22 -27
- classiq/qmod/builtins/functions/exponentiation.py +51 -2
- classiq/qmod/builtins/functions/mcx_func.py +7 -0
- classiq/qmod/builtins/functions/standard_gates.py +46 -27
- classiq/qmod/builtins/operations.py +165 -79
- classiq/qmod/builtins/structs.py +24 -91
- classiq/qmod/cfunc.py +3 -2
- classiq/qmod/classical_function.py +2 -1
- classiq/qmod/cparam.py +2 -8
- classiq/qmod/create_model_function.py +7 -7
- classiq/qmod/declaration_inferrer.py +33 -30
- classiq/qmod/expression_query.py +7 -4
- classiq/qmod/model_state_container.py +2 -2
- classiq/qmod/native/pretty_printer.py +25 -14
- classiq/qmod/pretty_print/expression_to_python.py +5 -3
- classiq/qmod/pretty_print/pretty_printer.py +39 -17
- classiq/qmod/python_classical_type.py +40 -13
- classiq/qmod/qfunc.py +124 -19
- classiq/qmod/qmod_constant.py +2 -2
- classiq/qmod/qmod_parameter.py +5 -2
- classiq/qmod/qmod_variable.py +47 -46
- classiq/qmod/quantum_callable.py +18 -13
- classiq/qmod/quantum_expandable.py +31 -26
- classiq/qmod/quantum_function.py +84 -36
- classiq/qmod/semantics/annotation/call_annotation.py +5 -5
- classiq/qmod/semantics/error_manager.py +12 -14
- classiq/qmod/semantics/lambdas.py +1 -2
- classiq/qmod/semantics/validation/types_validation.py +1 -2
- classiq/qmod/symbolic.py +2 -4
- classiq/qmod/utilities.py +13 -20
- classiq/qmod/write_qmod.py +3 -4
- classiq/quantum_program.py +1 -3
- classiq/synthesis.py +11 -7
- {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/METADATA +2 -3
- {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/RECORD +271 -299
- {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/WHEEL +1 -1
- classiq/applications/chemistry/ansatz_parameters.py +0 -29
- classiq/applications/chemistry/chemistry_execution_parameters.py +0 -16
- classiq/applications/chemistry/chemistry_model_constructor.py +0 -532
- classiq/applications/chemistry/ground_state_problem.py +0 -42
- classiq/applications/qsvm/__init__.py +0 -8
- classiq/applications/qsvm/qsvm.py +0 -11
- classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -129
- classiq/execution/iqcc.py +0 -128
- classiq/interface/applications/qsvm.py +0 -117
- classiq/interface/chemistry/elements.py +0 -120
- classiq/interface/chemistry/fermionic_operator.py +0 -208
- classiq/interface/chemistry/ground_state_problem.py +0 -132
- classiq/interface/chemistry/ground_state_result.py +0 -8
- classiq/interface/chemistry/molecule.py +0 -71
- classiq/interface/execution/iqcc.py +0 -44
- classiq/interface/generator/application_apis/chemistry_declarations.py +0 -69
- classiq/interface/generator/application_apis/entangler_declarations.py +0 -29
- classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
- classiq/interface/generator/chemistry_function_params.py +0 -50
- classiq/interface/generator/entangler_params.py +0 -72
- classiq/interface/generator/entanglers.py +0 -14
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +0 -27
- classiq/interface/generator/hartree_fock.py +0 -26
- classiq/interface/generator/hva.py +0 -22
- classiq/interface/generator/linear_pauli_rotations.py +0 -92
- classiq/interface/generator/qft.py +0 -37
- classiq/interface/generator/qsvm.py +0 -96
- classiq/interface/generator/state_preparation/__init__.py +0 -14
- classiq/interface/generator/state_preparation/bell_state_preparation.py +0 -27
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +0 -28
- classiq/interface/generator/state_preparation/distributions.py +0 -53
- classiq/interface/generator/state_preparation/exponential_state_preparation.py +0 -14
- classiq/interface/generator/state_preparation/ghz_state_preparation.py +0 -14
- classiq/interface/generator/state_preparation/metrics.py +0 -41
- classiq/interface/generator/state_preparation/state_preparation.py +0 -113
- classiq/interface/generator/state_preparation/state_preparation_abc.py +0 -24
- classiq/interface/generator/state_preparation/uniform_distibution_state_preparation.py +0 -13
- classiq/interface/generator/state_preparation/w_state_preparation.py +0 -13
- classiq/interface/generator/ucc.py +0 -74
- classiq/interface/helpers/backward_compatibility.py +0 -9
- classiq/model_expansions/transformers/type_modifier_inference.py +0 -392
- classiq/open_library/functions/lookup_table.py +0 -58
- classiq/qmod/builtins/functions/chemistry.py +0 -123
- classiq/qmod/builtins/functions/qsvm.py +0 -24
- {classiq-0.93.0.dist-info → classiq-0.99.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import ast
|
|
2
|
-
from typing import Any, cast
|
|
3
|
-
|
|
4
|
-
import sympy
|
|
5
|
-
|
|
6
|
-
MAX_PIECEWISE_LOOPS = 1000
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# FIXME: Remove with deprecation (CLS-3214)
|
|
10
|
-
class QmodExpressionBwc(ast.NodeTransformer):
|
|
11
|
-
def visit_Call(self, node: ast.Call) -> Any:
|
|
12
|
-
node = cast(ast.Call, self.generic_visit(node))
|
|
13
|
-
if not isinstance(node.func, ast.Name):
|
|
14
|
-
return node
|
|
15
|
-
func = node.func.id
|
|
16
|
-
args = node.args
|
|
17
|
-
kwargs = node.keywords
|
|
18
|
-
num_args = len(args)
|
|
19
|
-
num_kwargs = len(kwargs)
|
|
20
|
-
|
|
21
|
-
if func == "BitwiseNot":
|
|
22
|
-
if num_args != 1 or num_kwargs != 0:
|
|
23
|
-
return node
|
|
24
|
-
return ast.UnaryOp(op=ast.Invert(), operand=args[0])
|
|
25
|
-
if func == "LShift":
|
|
26
|
-
if num_args != 2 or num_kwargs != 0:
|
|
27
|
-
return node
|
|
28
|
-
return ast.BinOp(left=args[0], op=ast.LShift(), right=args[1])
|
|
29
|
-
if func == "RShift":
|
|
30
|
-
if num_args != 2 or num_kwargs != 0:
|
|
31
|
-
return node
|
|
32
|
-
return ast.BinOp(left=args[0], op=ast.RShift(), right=args[1])
|
|
33
|
-
if func == "BitwiseOr":
|
|
34
|
-
if num_args != 2 or num_kwargs != 0:
|
|
35
|
-
return node
|
|
36
|
-
return ast.BinOp(left=args[0], op=ast.BitOr(), right=args[1])
|
|
37
|
-
if func == "BitwiseXor":
|
|
38
|
-
if num_args != 2 or num_kwargs != 0:
|
|
39
|
-
return node
|
|
40
|
-
return ast.BinOp(left=args[0], op=ast.BitXor(), right=args[1])
|
|
41
|
-
if func == "BitwiseAnd":
|
|
42
|
-
if num_args != 2 or num_kwargs != 0:
|
|
43
|
-
return node
|
|
44
|
-
return ast.BinOp(left=args[0], op=ast.BitAnd(), right=args[1])
|
|
45
|
-
|
|
46
|
-
if func == "LogicalXor":
|
|
47
|
-
if num_args != 2 or num_kwargs != 0:
|
|
48
|
-
return node
|
|
49
|
-
return ast.BinOp(left=args[0], op=ast.BitXor(), right=args[1])
|
|
50
|
-
|
|
51
|
-
if func == "Eq":
|
|
52
|
-
if num_args != 2 or num_kwargs != 0:
|
|
53
|
-
return node
|
|
54
|
-
return ast.Compare(left=args[0], ops=[ast.Eq()], comparators=[args[1]])
|
|
55
|
-
if func == "Ne":
|
|
56
|
-
if num_args != 2 or num_kwargs != 0:
|
|
57
|
-
return node
|
|
58
|
-
return ast.Compare(left=args[0], ops=[ast.NotEq()], comparators=[args[1]])
|
|
59
|
-
if func == "Lt":
|
|
60
|
-
if num_args != 2 or num_kwargs != 0:
|
|
61
|
-
return node
|
|
62
|
-
return ast.Compare(left=args[0], ops=[ast.Lt()], comparators=[args[1]])
|
|
63
|
-
if func == "Le":
|
|
64
|
-
if num_args != 2 or num_kwargs != 0:
|
|
65
|
-
return node
|
|
66
|
-
return ast.Compare(left=args[0], ops=[ast.LtE()], comparators=[args[1]])
|
|
67
|
-
if func == "Gt":
|
|
68
|
-
if num_args != 2 or num_kwargs != 0:
|
|
69
|
-
return node
|
|
70
|
-
return ast.Compare(left=args[0], ops=[ast.Gt()], comparators=[args[1]])
|
|
71
|
-
if func == "Ge":
|
|
72
|
-
if num_args != 2 or num_kwargs != 0:
|
|
73
|
-
return node
|
|
74
|
-
return ast.Compare(left=args[0], ops=[ast.GtE()], comparators=[args[1]])
|
|
75
|
-
|
|
76
|
-
if func == "do_subscript":
|
|
77
|
-
if num_args != 2 or num_kwargs != 0:
|
|
78
|
-
return node
|
|
79
|
-
return ast.Subscript(value=args[0], slice=args[1])
|
|
80
|
-
|
|
81
|
-
if func == "get_field":
|
|
82
|
-
if num_args != 2 or num_kwargs != 0:
|
|
83
|
-
return node
|
|
84
|
-
attr = args[1]
|
|
85
|
-
if not isinstance(attr, ast.Constant):
|
|
86
|
-
return node
|
|
87
|
-
return ast.Attribute(value=args[0], attr=attr.value)
|
|
88
|
-
|
|
89
|
-
if func == "Piecewise":
|
|
90
|
-
if num_args == 0:
|
|
91
|
-
return node
|
|
92
|
-
first_piece = args[0]
|
|
93
|
-
if not isinstance(first_piece, ast.Tuple) or len(first_piece.elts) != 2:
|
|
94
|
-
return node
|
|
95
|
-
first_cond = first_piece.elts[1]
|
|
96
|
-
if isinstance(first_cond, ast.BinOp):
|
|
97
|
-
first_cond = first_cond.right
|
|
98
|
-
if not isinstance(first_cond, ast.Compare) or len(first_cond.ops) != 1:
|
|
99
|
-
return node
|
|
100
|
-
index_var_node = first_cond.left
|
|
101
|
-
if not isinstance(index_var_node, ast.Name):
|
|
102
|
-
return node
|
|
103
|
-
index_var = index_var_node.id
|
|
104
|
-
last_cond = args[-1]
|
|
105
|
-
if not isinstance(last_cond, ast.Tuple) or len(last_cond.elts) != 2:
|
|
106
|
-
return node
|
|
107
|
-
last_value = last_cond.elts[0]
|
|
108
|
-
if not isinstance(last_value, ast.Constant) and (
|
|
109
|
-
not isinstance(last_value, ast.UnaryOp)
|
|
110
|
-
or not isinstance(last_value.operand, ast.Constant)
|
|
111
|
-
):
|
|
112
|
-
return node
|
|
113
|
-
dummy_var_name = f"{index_var}_not_it"
|
|
114
|
-
last_cond.elts[0] = ast.Name(id=dummy_var_name)
|
|
115
|
-
items: list = []
|
|
116
|
-
idx = 0
|
|
117
|
-
for idx in range(MAX_PIECEWISE_LOOPS):
|
|
118
|
-
item = sympy.sympify(ast.unparse(node), locals={index_var: idx})
|
|
119
|
-
if str(item) == dummy_var_name:
|
|
120
|
-
items.append(last_value)
|
|
121
|
-
break
|
|
122
|
-
items.append(ast.parse(str(item), mode="eval").body)
|
|
123
|
-
if idx == MAX_PIECEWISE_LOOPS:
|
|
124
|
-
return node
|
|
125
|
-
return ast.Subscript(
|
|
126
|
-
value=ast.List(elts=items), slice=ast.Name(id=index_var)
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
return node
|
classiq/execution/iqcc.py
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import webbrowser
|
|
3
|
-
|
|
4
|
-
from classiq.interface.exceptions import ClassiqError
|
|
5
|
-
from classiq.interface.execution.iqcc import (
|
|
6
|
-
IQCCAuthItemDetails,
|
|
7
|
-
IQCCInitAuthData,
|
|
8
|
-
IQCCListAuthMethods,
|
|
9
|
-
IQCCListAuthTargets,
|
|
10
|
-
IQCCProbeAuthData,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
from classiq._internals.api_wrapper import ApiWrapper
|
|
14
|
-
from classiq._internals.async_utils import syncify_function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
async def list_iqcc_auth_scopes_async() -> list[IQCCAuthItemDetails]:
|
|
18
|
-
"""List available authentication scopes in IQCC Bounday.
|
|
19
|
-
|
|
20
|
-
Returns:
|
|
21
|
-
The available authentication scopes.
|
|
22
|
-
"""
|
|
23
|
-
response = await ApiWrapper().call_iqcc_list_auth_scopes()
|
|
24
|
-
return response.items
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
list_iqcc_auth_scopes = syncify_function(list_iqcc_auth_scopes_async)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
async def list_iqcc_auth_methods_async(auth_scope_id: str) -> list[IQCCAuthItemDetails]:
|
|
31
|
-
"""List available authentication methods in IQCC Bounday for a specific scope.
|
|
32
|
-
|
|
33
|
-
Args:
|
|
34
|
-
auth_scope_id: The ID of the IQCC Boundary authentication scope.
|
|
35
|
-
|
|
36
|
-
Returns:
|
|
37
|
-
The available authentication methods.
|
|
38
|
-
"""
|
|
39
|
-
response = await ApiWrapper().call_iqcc_list_auth_methods(
|
|
40
|
-
IQCCListAuthMethods(auth_scope_id=auth_scope_id)
|
|
41
|
-
)
|
|
42
|
-
return response.items
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
list_iqcc_auth_methods = syncify_function(list_iqcc_auth_methods_async)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
async def generate_iqcc_token_async(
|
|
49
|
-
auth_scope_id: str,
|
|
50
|
-
auth_method_id: str,
|
|
51
|
-
timeout: float = 120,
|
|
52
|
-
probe_interval: float = 1,
|
|
53
|
-
print_auth_url: bool = True,
|
|
54
|
-
) -> str:
|
|
55
|
-
"""Interactively generate a token for use in IQCC backends.
|
|
56
|
-
|
|
57
|
-
Args:
|
|
58
|
-
auth_scope_id: The ID of the IQCC Boundary authentication scope.
|
|
59
|
-
auth_method_id: The ID of the IQCC Boundary authentication method.
|
|
60
|
-
timeout: Number of seconds to wait for the interactive authentication to complete.
|
|
61
|
-
probe_interval: Number of seconds to wait between probes of the authentication.
|
|
62
|
-
print_auth_url: Whether to print the authentication URL, useful for headless machines with no browser.
|
|
63
|
-
|
|
64
|
-
Returns:
|
|
65
|
-
The authentication token string to use directly in `IQCCBackendPreferences`.
|
|
66
|
-
|
|
67
|
-
Raises:
|
|
68
|
-
ClassiqError: In case timeout has reached before a successful authentication.
|
|
69
|
-
"""
|
|
70
|
-
initiate_response = await ApiWrapper().call_iqcc_init_auth(
|
|
71
|
-
IQCCInitAuthData(auth_scope_id=auth_scope_id, auth_method_id=auth_method_id)
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
if print_auth_url:
|
|
75
|
-
print("Please proceed with authentication on your web browser.") # noqa: T201
|
|
76
|
-
print("If no window has opened, use this link to authenticate:") # noqa: T201
|
|
77
|
-
print(initiate_response.auth_url) # noqa: T201
|
|
78
|
-
|
|
79
|
-
webbrowser.open_new_tab(initiate_response.auth_url)
|
|
80
|
-
|
|
81
|
-
start_time = time.monotonic()
|
|
82
|
-
while True:
|
|
83
|
-
time.sleep(probe_interval)
|
|
84
|
-
probe_response = await ApiWrapper().call_iqcc_probe_auth(
|
|
85
|
-
IQCCProbeAuthData(
|
|
86
|
-
auth_scope_id=auth_scope_id,
|
|
87
|
-
auth_method_id=auth_method_id,
|
|
88
|
-
token_id=initiate_response.token_id,
|
|
89
|
-
)
|
|
90
|
-
)
|
|
91
|
-
if probe_response is not None:
|
|
92
|
-
return probe_response.auth_token
|
|
93
|
-
|
|
94
|
-
if time.monotonic() - start_time > timeout:
|
|
95
|
-
raise ClassiqError(
|
|
96
|
-
f"Timeout has reached while probing IQCC authentication. Please try again and make sure to authenticate within {timeout} seconds, or increase the timeout."
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
generate_iqcc_token = syncify_function(generate_iqcc_token_async)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
async def list_iqcc_auth_targets_async(
|
|
104
|
-
auth_scope_id: str,
|
|
105
|
-
auth_method_id: str,
|
|
106
|
-
auth_token: str,
|
|
107
|
-
) -> list[IQCCAuthItemDetails]:
|
|
108
|
-
"""List available authentication targets in IQCC Boundary for the user.
|
|
109
|
-
|
|
110
|
-
Args:
|
|
111
|
-
auth_scope_id: The ID of the IQCC Boundary authentication scope.
|
|
112
|
-
auth_method_id: The ID of the IQCC Boundary authentication method.
|
|
113
|
-
auth_token: The authentication token string returned from `generate_iqcc_token_async`.
|
|
114
|
-
|
|
115
|
-
Returns:
|
|
116
|
-
The available authentication targets.
|
|
117
|
-
"""
|
|
118
|
-
response = await ApiWrapper().call_iqcc_list_auth_targets(
|
|
119
|
-
IQCCListAuthTargets(
|
|
120
|
-
auth_scope_id=auth_scope_id,
|
|
121
|
-
auth_method_id=auth_method_id,
|
|
122
|
-
auth_token=auth_token,
|
|
123
|
-
)
|
|
124
|
-
)
|
|
125
|
-
return response.items
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
list_iqcc_auth_target = syncify_function(list_iqcc_auth_targets_async)
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
from collections.abc import Iterable as IterableType, Sequence
|
|
2
|
-
from typing import (
|
|
3
|
-
Any,
|
|
4
|
-
Optional,
|
|
5
|
-
Union,
|
|
6
|
-
)
|
|
7
|
-
|
|
8
|
-
import numpy as np
|
|
9
|
-
import pydantic
|
|
10
|
-
from numpy.typing import ArrayLike
|
|
11
|
-
from pydantic import ConfigDict, field_validator
|
|
12
|
-
|
|
13
|
-
from classiq.interface.helpers.versioned_model import VersionedModel
|
|
14
|
-
|
|
15
|
-
DataList = list[list[float]]
|
|
16
|
-
LabelsInt = list[int]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def listify(obj: Union[IterableType, ArrayLike]) -> list:
|
|
20
|
-
if isinstance(obj, np.ndarray):
|
|
21
|
-
return obj.tolist()
|
|
22
|
-
elif isinstance(obj, Sequence) and obj and isinstance(obj[0], np.ndarray):
|
|
23
|
-
return np.array(obj).tolist()
|
|
24
|
-
elif isinstance(obj, list):
|
|
25
|
-
return obj
|
|
26
|
-
else:
|
|
27
|
-
return list(obj) # type: ignore[arg-type]
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def validate_array_to_list(name: str) -> Any:
|
|
31
|
-
@field_validator(name, mode="before")
|
|
32
|
-
def _listify(cls: type[pydantic.BaseModel], value: Any) -> Any:
|
|
33
|
-
return listify(value)
|
|
34
|
-
|
|
35
|
-
return _listify
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Shape = tuple[int, ...]
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class QSVMInternalState(VersionedModel):
|
|
42
|
-
underscore_sparse: bool
|
|
43
|
-
class_weight: list
|
|
44
|
-
classes: list
|
|
45
|
-
underscore_gamma: float
|
|
46
|
-
underscore_base_fit: list
|
|
47
|
-
support: list
|
|
48
|
-
support_vectors: list
|
|
49
|
-
underscore_n_support: list
|
|
50
|
-
dual_coef_2: list
|
|
51
|
-
intercept: list
|
|
52
|
-
underscore_p_a: list
|
|
53
|
-
underscore_p_b: list
|
|
54
|
-
fit_status: int
|
|
55
|
-
shape_fit: Shape
|
|
56
|
-
underscore_intercept: list
|
|
57
|
-
dual_coef: list
|
|
58
|
-
|
|
59
|
-
class_weight__shape: Shape
|
|
60
|
-
classes__shape: Shape
|
|
61
|
-
underscore_base_fit__shape: Shape
|
|
62
|
-
support__shape: Shape
|
|
63
|
-
support_vectors__shape: Shape
|
|
64
|
-
underscore_n_support__shape: Shape
|
|
65
|
-
dual_coef_2__shape: Shape
|
|
66
|
-
intercept__shape: Shape
|
|
67
|
-
underscore_p_a__shape: Shape
|
|
68
|
-
underscore_p_b__shape: Shape
|
|
69
|
-
underscore_intercept__shape: Shape
|
|
70
|
-
dual_coef__shape: Shape
|
|
71
|
-
|
|
72
|
-
set_class_weight = validate_array_to_list("class_weight")
|
|
73
|
-
set_classes = validate_array_to_list("classes")
|
|
74
|
-
set_underscore_base_fit = validate_array_to_list("underscore_base_fit")
|
|
75
|
-
set_support = validate_array_to_list("support")
|
|
76
|
-
set_support_vectors = validate_array_to_list("support_vectors")
|
|
77
|
-
set_underscore_n_support = validate_array_to_list("underscore_n_support")
|
|
78
|
-
set_dual_coef_2 = validate_array_to_list("dual_coef_2")
|
|
79
|
-
set_intercept = validate_array_to_list("intercept")
|
|
80
|
-
set_underscore_p_a = validate_array_to_list("underscore_p_a")
|
|
81
|
-
set_underscore_p_b = validate_array_to_list("underscore_p_b")
|
|
82
|
-
set_underscore_intercept = validate_array_to_list("underscore_intercept")
|
|
83
|
-
set_dual_coef = validate_array_to_list("dual_coef")
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class QSVMData(VersionedModel):
|
|
87
|
-
data: DataList
|
|
88
|
-
labels: Optional[LabelsInt] = None
|
|
89
|
-
internal_state: Optional[QSVMInternalState] = None
|
|
90
|
-
model_config = ConfigDict(extra="forbid")
|
|
91
|
-
|
|
92
|
-
@pydantic.field_validator("data", mode="before")
|
|
93
|
-
@classmethod
|
|
94
|
-
def set_data(cls, data: Union[IterableType, ArrayLike]) -> list:
|
|
95
|
-
return listify(data)
|
|
96
|
-
|
|
97
|
-
@pydantic.field_validator("labels", mode="before")
|
|
98
|
-
@classmethod
|
|
99
|
-
def set_labels(
|
|
100
|
-
cls, labels: Optional[Union[IterableType, ArrayLike]]
|
|
101
|
-
) -> Optional[list]:
|
|
102
|
-
if labels is None:
|
|
103
|
-
return None
|
|
104
|
-
else:
|
|
105
|
-
return listify(labels)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class QSVMTestResult(VersionedModel):
|
|
109
|
-
data: float # between 0 to 1
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class QSVMPredictResult(VersionedModel):
|
|
113
|
-
data: list # serialized np.array
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
Data = Union[DataList, np.ndarray]
|
|
117
|
-
Labels = Union[list[Any], np.ndarray]
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
ELEMENTS = [
|
|
2
|
-
"H",
|
|
3
|
-
"He",
|
|
4
|
-
"Li",
|
|
5
|
-
"Be",
|
|
6
|
-
"B",
|
|
7
|
-
"C",
|
|
8
|
-
"N",
|
|
9
|
-
"O",
|
|
10
|
-
"F",
|
|
11
|
-
"Ne",
|
|
12
|
-
"Na",
|
|
13
|
-
"Mg",
|
|
14
|
-
"Al",
|
|
15
|
-
"Si",
|
|
16
|
-
"P",
|
|
17
|
-
"S",
|
|
18
|
-
"Cl",
|
|
19
|
-
"Ar",
|
|
20
|
-
"K",
|
|
21
|
-
"Ca",
|
|
22
|
-
"Sc",
|
|
23
|
-
"Ti",
|
|
24
|
-
"V",
|
|
25
|
-
"Cr",
|
|
26
|
-
"Mn",
|
|
27
|
-
"Fe",
|
|
28
|
-
"Co",
|
|
29
|
-
"Ni",
|
|
30
|
-
"Cu",
|
|
31
|
-
"Zn",
|
|
32
|
-
"Ga",
|
|
33
|
-
"Ge",
|
|
34
|
-
"As",
|
|
35
|
-
"Se",
|
|
36
|
-
"Br",
|
|
37
|
-
"Kr",
|
|
38
|
-
"Rb",
|
|
39
|
-
"Sr",
|
|
40
|
-
"Y",
|
|
41
|
-
"Zr",
|
|
42
|
-
"Nb",
|
|
43
|
-
"Mo",
|
|
44
|
-
"Tc",
|
|
45
|
-
"Ru",
|
|
46
|
-
"Rh",
|
|
47
|
-
"Pd",
|
|
48
|
-
"Ag",
|
|
49
|
-
"Cd",
|
|
50
|
-
"In",
|
|
51
|
-
"Sn",
|
|
52
|
-
"Sb",
|
|
53
|
-
"Te",
|
|
54
|
-
"I",
|
|
55
|
-
"Xe",
|
|
56
|
-
"Cs",
|
|
57
|
-
"Ba",
|
|
58
|
-
"La",
|
|
59
|
-
"Ce",
|
|
60
|
-
"Pr",
|
|
61
|
-
"Nd",
|
|
62
|
-
"Pm",
|
|
63
|
-
"Sm",
|
|
64
|
-
"Eu",
|
|
65
|
-
"Gd",
|
|
66
|
-
"Tb",
|
|
67
|
-
"Dy",
|
|
68
|
-
"Ho",
|
|
69
|
-
"Er",
|
|
70
|
-
"Tm",
|
|
71
|
-
"Yb",
|
|
72
|
-
"Lu",
|
|
73
|
-
"Hf",
|
|
74
|
-
"Ta",
|
|
75
|
-
"W",
|
|
76
|
-
"Re",
|
|
77
|
-
"Os",
|
|
78
|
-
"Ir",
|
|
79
|
-
"Pt",
|
|
80
|
-
"Au",
|
|
81
|
-
"Hg",
|
|
82
|
-
"Tl",
|
|
83
|
-
"Pb",
|
|
84
|
-
"Bi",
|
|
85
|
-
"Po",
|
|
86
|
-
"At",
|
|
87
|
-
"Rn",
|
|
88
|
-
"Fr",
|
|
89
|
-
"Ra",
|
|
90
|
-
"Ac",
|
|
91
|
-
"Th",
|
|
92
|
-
"Pa",
|
|
93
|
-
"U",
|
|
94
|
-
"Np",
|
|
95
|
-
"Pu",
|
|
96
|
-
"Am",
|
|
97
|
-
"Cm",
|
|
98
|
-
"Bk",
|
|
99
|
-
"Cf",
|
|
100
|
-
"Es",
|
|
101
|
-
"Fm",
|
|
102
|
-
"Md",
|
|
103
|
-
"No",
|
|
104
|
-
"Lr",
|
|
105
|
-
"Rf",
|
|
106
|
-
"Db",
|
|
107
|
-
"Sg",
|
|
108
|
-
"Bh",
|
|
109
|
-
"Hs",
|
|
110
|
-
"Mt",
|
|
111
|
-
"Ds",
|
|
112
|
-
"Rg",
|
|
113
|
-
"Cn",
|
|
114
|
-
"Nh",
|
|
115
|
-
"Fl",
|
|
116
|
-
"Mc",
|
|
117
|
-
"Lv",
|
|
118
|
-
"Ts",
|
|
119
|
-
"Og",
|
|
120
|
-
]
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import itertools
|
|
4
|
-
from typing import Union
|
|
5
|
-
|
|
6
|
-
import numpy as np
|
|
7
|
-
import pydantic
|
|
8
|
-
from pydantic import ConfigDict
|
|
9
|
-
|
|
10
|
-
from classiq.interface.exceptions import ClassiqValueError
|
|
11
|
-
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
|
12
|
-
HashablePydanticBaseModel,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
LadderOperator = tuple[str, int]
|
|
16
|
-
FermionicOperatorTuple = tuple["FermionicOperator", float]
|
|
17
|
-
|
|
18
|
-
_SUBSCRIPT_UNICODE_CHARS = {
|
|
19
|
-
"0": "\u2080",
|
|
20
|
-
"1": "\u2081",
|
|
21
|
-
"2": "\u2082",
|
|
22
|
-
"3": "\u2083",
|
|
23
|
-
"4": "\u2084",
|
|
24
|
-
"5": "\u2085",
|
|
25
|
-
"6": "\u2086",
|
|
26
|
-
"7": "\u2087",
|
|
27
|
-
"8": "\u2088",
|
|
28
|
-
"9": "\u2089",
|
|
29
|
-
}
|
|
30
|
-
_SUPERSCRIPT_PLUS = "\u207a"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class FermionicOperator(HashablePydanticBaseModel):
|
|
34
|
-
"""
|
|
35
|
-
Specification of a Fermionic operator.
|
|
36
|
-
Input:
|
|
37
|
-
List of ladder operators, each ladder operator is described by a tuple of its
|
|
38
|
-
index and a character indicating if it's a creation ('+') or annihilation operator ('-').
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
op_list: list = pydantic.Field(
|
|
42
|
-
description=(
|
|
43
|
-
"A list of tuples each containing an index and a character; for "
|
|
44
|
-
"example [('+', 0), ('-', 1)]."
|
|
45
|
-
),
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
@staticmethod
|
|
49
|
-
def _validate_single_op(op: tuple) -> LadderOperator:
|
|
50
|
-
if not isinstance(op, tuple):
|
|
51
|
-
try: # type: ignore[unreachable] # it is reachable...
|
|
52
|
-
op = tuple(op)
|
|
53
|
-
except Exception as exc:
|
|
54
|
-
raise ClassiqValueError("Ladder operator should be a tuple.") from exc
|
|
55
|
-
if len(op) != 2:
|
|
56
|
-
raise ClassiqValueError(
|
|
57
|
-
"Ladder operator tuple should be of length two; for example ('+', 1)."
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
op_symbol = op[0]
|
|
61
|
-
if op_symbol == "LadderOperator.PLUS":
|
|
62
|
-
op_symbol = "+"
|
|
63
|
-
elif op_symbol == "LadderOperator.MINUS":
|
|
64
|
-
op_symbol = "-"
|
|
65
|
-
if op_symbol not in ("+", "-"):
|
|
66
|
-
raise ClassiqValueError(
|
|
67
|
-
f"The first term in a ladder operator tuple indicates if its a raising "
|
|
68
|
-
f"(LadderOperator.PLUS / '+') or lowering (LadderOperator.MINUS / '-') "
|
|
69
|
-
f"operator. Received {op_symbol}"
|
|
70
|
-
)
|
|
71
|
-
op_index = op[1]
|
|
72
|
-
if not isinstance(op_index, int):
|
|
73
|
-
raise ClassiqValueError(
|
|
74
|
-
"The second term in a ladder operator tuple indicates its index and should be of type int"
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
return (op_symbol, op_index)
|
|
78
|
-
|
|
79
|
-
@pydantic.field_validator("op_list")
|
|
80
|
-
@classmethod
|
|
81
|
-
def _validate_op_list(cls, op_list: list) -> list:
|
|
82
|
-
return list(map(cls._validate_single_op, op_list))
|
|
83
|
-
|
|
84
|
-
def __mul__(self, coeff: Union[float, int]) -> SummedFermionicOperator:
|
|
85
|
-
if isinstance(coeff, (float, int)):
|
|
86
|
-
return SummedFermionicOperator(op_list=[(self, float(coeff))])
|
|
87
|
-
raise ClassiqValueError(
|
|
88
|
-
"The coefficient multiplying Fermionic Operator should be of type float"
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
__rmul__ = __mul__
|
|
92
|
-
|
|
93
|
-
def __add__(
|
|
94
|
-
self, other: Union[SummedFermionicOperator, FermionicOperator]
|
|
95
|
-
) -> SummedFermionicOperator:
|
|
96
|
-
if isinstance(other, SummedFermionicOperator):
|
|
97
|
-
return SummedFermionicOperator(op_list=[(self, 1.0)] + other.op_list)
|
|
98
|
-
elif isinstance(other, FermionicOperator):
|
|
99
|
-
return SummedFermionicOperator(op_list=[(self, 1.0)] + [(other, 1.0)])
|
|
100
|
-
raise ClassiqValueError(
|
|
101
|
-
"FermionicOperator can be summed together only with type FermionicOperator or SummedFermionicOperator"
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
model_config = ConfigDict(frozen=True)
|
|
105
|
-
|
|
106
|
-
@staticmethod
|
|
107
|
-
def _to_ladder_op(char: str) -> str:
|
|
108
|
-
return "a" + _SUPERSCRIPT_PLUS if char == "+" else "a"
|
|
109
|
-
|
|
110
|
-
@staticmethod
|
|
111
|
-
def _to_subscript(num: int) -> str:
|
|
112
|
-
return "".join(_SUBSCRIPT_UNICODE_CHARS[digit] for digit in str(num))
|
|
113
|
-
|
|
114
|
-
def __str__(self) -> str:
|
|
115
|
-
return "".join(
|
|
116
|
-
f"{self._to_ladder_op(char)}{self._to_subscript(index)}"
|
|
117
|
-
for (char, index) in self.op_list
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
@property
|
|
121
|
-
def all_indices(self) -> set[int]:
|
|
122
|
-
return {op[1] for op in self.op_list}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
class SummedFermionicOperator(HashablePydanticBaseModel):
|
|
126
|
-
"""
|
|
127
|
-
Specification of a summed Fermionic operator.
|
|
128
|
-
Input:
|
|
129
|
-
List of fermionic operators tuples, The first term in the tuple is the FermionicOperator and the second term is its coefficient.
|
|
130
|
-
For example:
|
|
131
|
-
op1 = FermionicOperator(op_list=[('+', 0), ('-', 1)])
|
|
132
|
-
op2 = FermionicOperator(op_list=[('-', 0), ('-', 1)])
|
|
133
|
-
summed_operator = SummedFermionicOperator(op_list=[(op1, 0.2), (op2, 6.7)])
|
|
134
|
-
"""
|
|
135
|
-
|
|
136
|
-
op_list: list = pydantic.Field(
|
|
137
|
-
description="A list of tuples each containing a FermionicOperator and a coefficient.",
|
|
138
|
-
)
|
|
139
|
-
model_config = ConfigDict(frozen=True)
|
|
140
|
-
|
|
141
|
-
@staticmethod
|
|
142
|
-
def _validate_single_op(op: tuple) -> FermionicOperatorTuple:
|
|
143
|
-
# is it tuple - if not, convert to tuple
|
|
144
|
-
if not isinstance(op, tuple):
|
|
145
|
-
try: # type: ignore[unreachable] # it is reachable...
|
|
146
|
-
op = tuple(op)
|
|
147
|
-
except Exception as exc:
|
|
148
|
-
raise ClassiqValueError("Operator should be a tuple.") from exc
|
|
149
|
-
if len(op) != 2:
|
|
150
|
-
raise ClassiqValueError("Operator tuple should be of length two.")
|
|
151
|
-
|
|
152
|
-
# is it FermionicOperator - if not, convert to FermionicOperator
|
|
153
|
-
if not isinstance(op[0], FermionicOperator):
|
|
154
|
-
try:
|
|
155
|
-
op = (FermionicOperator(**op[0]), op[1])
|
|
156
|
-
except Exception as exc:
|
|
157
|
-
raise ClassiqValueError(
|
|
158
|
-
"The first term in the operator tuple should be an instance of the FermionicOperator class"
|
|
159
|
-
) from exc
|
|
160
|
-
|
|
161
|
-
if not isinstance(op[1], float):
|
|
162
|
-
raise ClassiqValueError(
|
|
163
|
-
"The second term in the operator tuple indicates its coefficient and should be of type float"
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
return op # type: ignore[return-value] # mypy thinks that it is `Tuple[Any, ...]`, though the asserts here tell otherwise..
|
|
167
|
-
|
|
168
|
-
@pydantic.field_validator("op_list")
|
|
169
|
-
@classmethod
|
|
170
|
-
def _validate_op_list(cls, op_list: list) -> list:
|
|
171
|
-
return list(map(cls._validate_single_op, op_list))
|
|
172
|
-
|
|
173
|
-
def __add__(
|
|
174
|
-
self, other: Union[SummedFermionicOperator, FermionicOperator]
|
|
175
|
-
) -> SummedFermionicOperator:
|
|
176
|
-
if isinstance(other, SummedFermionicOperator):
|
|
177
|
-
return SummedFermionicOperator(op_list=self.op_list + other.op_list)
|
|
178
|
-
elif isinstance(other, FermionicOperator):
|
|
179
|
-
return SummedFermionicOperator(op_list=self.op_list + [(other, 1.0)])
|
|
180
|
-
raise ClassiqValueError(
|
|
181
|
-
"FermionicOperator can be summed together only with type FermionicOperator or SummedFermionicOperator"
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
def is_close(self, other: SummedFermionicOperator) -> bool:
|
|
185
|
-
if not isinstance(other, SummedFermionicOperator):
|
|
186
|
-
return False # type: ignore[unreachable]
|
|
187
|
-
|
|
188
|
-
if len(self.op_list) != len(other.op_list):
|
|
189
|
-
return False
|
|
190
|
-
|
|
191
|
-
for (op1, coeff1), (op2, coeff2) in zip(self.op_list, other.op_list):
|
|
192
|
-
if op1 != op2 or not np.isclose(coeff1, coeff2):
|
|
193
|
-
return False
|
|
194
|
-
|
|
195
|
-
return True
|
|
196
|
-
|
|
197
|
-
@property
|
|
198
|
-
def _all_indices(self) -> set[int]:
|
|
199
|
-
return set(
|
|
200
|
-
itertools.chain.from_iterable(op.all_indices for op, _ in self.op_list)
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
@property
|
|
204
|
-
def num_qubits(self) -> int:
|
|
205
|
-
return len(self._all_indices)
|
|
206
|
-
|
|
207
|
-
def __str__(self) -> str:
|
|
208
|
-
return " + \n".join(str(op[1]) + " * " + str(op[0]) for op in self.op_list)
|