classiq 0.93.0__py3-none-any.whl → 0.94.1__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.
Potentially problematic release.
This version of classiq might be problematic. Click here for more details.
- classiq/__init__.py +6 -19
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +7 -7
- classiq/_analyzer_extras/interactive_hardware.py +19 -12
- classiq/_internals/api_wrapper.py +38 -52
- classiq/_internals/async_utils.py +4 -7
- classiq/_internals/authentication/auth0.py +3 -3
- classiq/_internals/authentication/device.py +4 -4
- classiq/_internals/authentication/password_manager.py +13 -13
- classiq/_internals/authentication/token_manager.py +4 -5
- classiq/_internals/client.py +17 -44
- classiq/_internals/config.py +1 -2
- 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/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 +8 -8
- classiq/applications/qnn/datasets/dataset_base_classes.py +6 -6
- classiq/applications/qnn/datasets/dataset_parity.py +6 -6
- classiq/applications/qnn/qlayer.py +8 -7
- classiq/applications/qnn/torch_utils.py +3 -4
- classiq/applications/qnn/types.py +2 -1
- classiq/applications/qsp/qsp.py +5 -4
- classiq/applications/qsvm/qsvm_data_generation.py +1 -2
- classiq/evaluators/classical_expression.py +0 -4
- classiq/evaluators/parameter_types.py +7 -8
- classiq/evaluators/qmod_annotated_expression.py +24 -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/classical_function_evaluation.py +4 -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/execution_session.py +18 -19
- classiq/execution/jobs.py +26 -26
- classiq/execution/qnn.py +1 -2
- classiq/execution/user_budgets.py +52 -7
- 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/applications/qsvm.py +5 -8
- classiq/interface/ast_node.py +3 -3
- classiq/interface/backend/backend_preferences.py +16 -16
- classiq/interface/backend/ionq/ionq_quantum_program.py +5 -5
- 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 +7 -7
- classiq/interface/exceptions.py +2 -3
- classiq/interface/execution/iqcc.py +1 -3
- 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 +2 -3
- classiq/interface/executor/vqe_result.py +5 -6
- classiq/interface/generator/ansatz_library.py +6 -8
- classiq/interface/generator/application_apis/__init__.py +0 -2
- 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 +7 -36
- 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 +2 -2
- 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 -20
- 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 -14
- classiq/interface/generator/functions/type_name.py +2 -2
- classiq/interface/generator/generated_circuit_data.py +12 -13
- 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 +8 -8
- 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/qsvm.py +2 -2
- classiq/interface/generator/quantum_function_call.py +8 -11
- classiq/interface/generator/quantum_program.py +12 -15
- 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/state_preparation/state_preparation.py +6 -8
- classiq/interface/generator/synthesis_execution_parameter.py +1 -3
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +2 -3
- classiq/interface/generator/transpiler_basis_gates.py +2 -4
- classiq/interface/generator/types/builtin_enum_declarations.py +0 -136
- 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 -2
- 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 +5 -5
- classiq/interface/jobs.py +3 -3
- classiq/interface/model/allocate.py +4 -4
- classiq/interface/model/block.py +2 -2
- classiq/interface/model/bounds.py +3 -3
- classiq/interface/model/control.py +1 -1
- classiq/interface/model/inplace_binary_operation.py +2 -2
- classiq/interface/model/model.py +4 -4
- classiq/interface/model/parameter.py +1 -3
- classiq/interface/model/port_declaration.py +1 -1
- 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 +4 -4
- classiq/interface/model/quantum_type.py +14 -14
- classiq/interface/model/validation_handle.py +2 -3
- classiq/interface/model/variable_declaration_statement.py +2 -2
- classiq/interface/pretty_print/expression_to_qmod.py +3 -4
- classiq/interface/server/routes.py +0 -4
- classiq/interface/source_reference.py +3 -4
- classiq/model_expansions/arithmetic.py +6 -7
- classiq/model_expansions/arithmetic_compute_result_attrs.py +4 -5
- 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 +1 -4
- classiq/model_expansions/interpreters/base_interpreter.py +2 -6
- 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 +3 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +317 -0
- classiq/model_expansions/visitors/variable_references.py +15 -14
- classiq/open_library/functions/__init__.py +6 -0
- classiq/open_library/functions/discrete_sine_cosine_transform.py +5 -5
- classiq/open_library/functions/grover.py +8 -10
- classiq/open_library/functions/modular_exponentiation.py +96 -8
- classiq/qmod/__init__.py +5 -2
- classiq/qmod/builtins/classical_execution_primitives.py +4 -11
- classiq/qmod/builtins/classical_functions.py +1 -42
- classiq/qmod/builtins/enums.py +0 -136
- classiq/qmod/builtins/functions/__init__.py +0 -13
- classiq/qmod/builtins/functions/allocation.py +4 -4
- classiq/qmod/builtins/functions/arithmetic.py +22 -27
- classiq/qmod/builtins/functions/standard_gates.py +27 -27
- classiq/qmod/builtins/operations.py +35 -58
- classiq/qmod/builtins/structs.py +2 -58
- 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/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 +139 -16
- classiq/qmod/qmod_constant.py +2 -2
- classiq/qmod/qmod_parameter.py +5 -2
- classiq/qmod/qmod_variable.py +47 -43
- classiq/qmod/quantum_callable.py +18 -13
- classiq/qmod/quantum_expandable.py +31 -26
- classiq/qmod/quantum_function.py +51 -32
- classiq/qmod/semantics/annotation/call_annotation.py +2 -2
- classiq/qmod/semantics/error_manager.py +5 -6
- 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 -10
- 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.94.1.dist-info}/METADATA +2 -3
- {classiq-0.93.0.dist-info → classiq-0.94.1.dist-info}/RECORD +238 -260
- 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/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -129
- 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/generator/application_apis/chemistry_declarations.py +0 -69
- classiq/interface/generator/application_apis/entangler_declarations.py +0 -29
- 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/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/ucc.py +0 -74
- classiq/interface/helpers/backward_compatibility.py +0 -9
- classiq/model_expansions/transformers/type_modifier_inference.py +0 -392
- classiq/qmod/builtins/functions/chemistry.py +0 -123
- {classiq-0.93.0.dist-info → classiq-0.94.1.dist-info}/WHEEL +0 -0
- {classiq-0.93.0.dist-info → classiq-0.94.1.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
|
|
@@ -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)
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import warnings
|
|
2
|
-
from typing import Annotated, Any, Literal, Optional, Union, cast
|
|
3
|
-
|
|
4
|
-
import pydantic
|
|
5
|
-
from pydantic import ConfigDict, Field
|
|
6
|
-
from pydantic_core.core_schema import ValidationInfo
|
|
7
|
-
|
|
8
|
-
from classiq.interface.chemistry.fermionic_operator import SummedFermionicOperator
|
|
9
|
-
from classiq.interface.chemistry.molecule import Molecule
|
|
10
|
-
from classiq.interface.enum_utils import StrEnum
|
|
11
|
-
from classiq.interface.exceptions import ClassiqDeprecationWarning, ClassiqValueError
|
|
12
|
-
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
|
13
|
-
HashablePydanticBaseModel,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
"""
|
|
17
|
-
The correct type hint is:
|
|
18
|
-
NumSpinUpParticles = pydantic.NonNegativeInt
|
|
19
|
-
NumSpinDownParticles = pydantic.NonNegativeInt
|
|
20
|
-
NumParticles = Tuple[NumSpinUpParticles, NumSpinDownParticles]
|
|
21
|
-
|
|
22
|
-
But:
|
|
23
|
-
A) the NonNegativeInt makes the ts-schemas have a `Minimum` object,
|
|
24
|
-
which is undefined, thus causing an error
|
|
25
|
-
B) a tuple of a specific size gives another, different error
|
|
26
|
-
|
|
27
|
-
Thus, we use `int` and manually check its value
|
|
28
|
-
And use a list, and manually check its length
|
|
29
|
-
"""
|
|
30
|
-
NumSpinUpParticles = pydantic.NonNegativeInt
|
|
31
|
-
NumSpinDownParticles = pydantic.NonNegativeInt
|
|
32
|
-
NumParticles = tuple[NumSpinUpParticles, NumSpinDownParticles]
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class FermionMapping(StrEnum):
|
|
36
|
-
JORDAN_WIGNER = "jordan_wigner"
|
|
37
|
-
PARITY = "parity"
|
|
38
|
-
BRAVYI_KITAEV = "bravyi_kitaev"
|
|
39
|
-
FAST_BRAVYI_KITAEV = "fast_bravyi_kitaev"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class GroundStateProblem(HashablePydanticBaseModel):
|
|
43
|
-
kind: str
|
|
44
|
-
|
|
45
|
-
mapping: FermionMapping = pydantic.Field(
|
|
46
|
-
default=FermionMapping.JORDAN_WIGNER,
|
|
47
|
-
description="Fermionic mapping type",
|
|
48
|
-
title="Fermion Mapping",
|
|
49
|
-
)
|
|
50
|
-
z2_symmetries: bool = pydantic.Field(
|
|
51
|
-
default=False,
|
|
52
|
-
description="whether to perform z2 symmetries reduction",
|
|
53
|
-
)
|
|
54
|
-
num_qubits: Optional[int] = pydantic.Field(default=None)
|
|
55
|
-
|
|
56
|
-
def __init__(self, /, **data: Any) -> None:
|
|
57
|
-
warnings.warn(
|
|
58
|
-
(
|
|
59
|
-
f"The class `{self.__class__.__name__}` is deprecated and will no "
|
|
60
|
-
"longer be supported starting on 2025-09-18 at the earliest. "
|
|
61
|
-
"For more information on Classiq's chemistry application, see "
|
|
62
|
-
"https://docs.classiq.io/latest/explore/applications/chemistry/classiq_chemistry_application/classiq_chemistry_application/."
|
|
63
|
-
),
|
|
64
|
-
category=ClassiqDeprecationWarning,
|
|
65
|
-
stacklevel=2,
|
|
66
|
-
)
|
|
67
|
-
super().__init__(**data)
|
|
68
|
-
|
|
69
|
-
@pydantic.field_validator("z2_symmetries")
|
|
70
|
-
@classmethod
|
|
71
|
-
def _validate_z2_symmetries(cls, z2_symmetries: bool, info: ValidationInfo) -> bool:
|
|
72
|
-
if (
|
|
73
|
-
z2_symmetries
|
|
74
|
-
and info.data.get("mapping") == FermionMapping.FAST_BRAVYI_KITAEV
|
|
75
|
-
):
|
|
76
|
-
raise ClassiqValueError(
|
|
77
|
-
"z2 symmetries reduction can not be used for fast_bravyi_kitaev mapping"
|
|
78
|
-
)
|
|
79
|
-
return z2_symmetries
|
|
80
|
-
|
|
81
|
-
model_config = ConfigDict(frozen=True)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class MoleculeProblem(GroundStateProblem):
|
|
85
|
-
kind: Literal["molecule"] = pydantic.Field(default="molecule")
|
|
86
|
-
|
|
87
|
-
molecule: Molecule
|
|
88
|
-
basis: str = pydantic.Field(default="sto3g", description="Molecular basis set")
|
|
89
|
-
freeze_core: bool = pydantic.Field(default=False)
|
|
90
|
-
remove_orbitals: list[int] = pydantic.Field(
|
|
91
|
-
default_factory=list, description="list of orbitals to remove"
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
class HamiltonianProblem(GroundStateProblem):
|
|
96
|
-
kind: Literal["hamiltonian"] = pydantic.Field(default="hamiltonian")
|
|
97
|
-
|
|
98
|
-
hamiltonian: SummedFermionicOperator = pydantic.Field(
|
|
99
|
-
description="Hamiltonian as a fermionic operator"
|
|
100
|
-
)
|
|
101
|
-
num_particles: list[pydantic.PositiveInt] = pydantic.Field(
|
|
102
|
-
description="Tuple containing the numbers of alpha particles and beta particles"
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
@pydantic.field_validator("num_particles", mode="before")
|
|
106
|
-
@classmethod
|
|
107
|
-
def _validate_num_particles(
|
|
108
|
-
cls,
|
|
109
|
-
num_particles: Union[
|
|
110
|
-
list[Union[int, float]], tuple[Union[int, float], Union[int, float]]
|
|
111
|
-
],
|
|
112
|
-
) -> list[int]:
|
|
113
|
-
assert isinstance(num_particles, (list, tuple))
|
|
114
|
-
assert len(num_particles) == 2
|
|
115
|
-
|
|
116
|
-
num_particles = [int(x) for x in num_particles]
|
|
117
|
-
|
|
118
|
-
assert num_particles[0] >= 1
|
|
119
|
-
assert num_particles[1] >= 1
|
|
120
|
-
|
|
121
|
-
return cast(list[int], num_particles)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
CHEMISTRY_PROBLEMS = (MoleculeProblem, HamiltonianProblem)
|
|
125
|
-
CHEMISTRY_PROBLEMS_TYPE = Annotated[
|
|
126
|
-
Union[MoleculeProblem, HamiltonianProblem],
|
|
127
|
-
Field(
|
|
128
|
-
discriminator="kind",
|
|
129
|
-
description="Ground state problem object describing the system.",
|
|
130
|
-
),
|
|
131
|
-
]
|
|
132
|
-
CHEMISTRY_ANSATZ_NAMES = ["hw_efficient", "ucc", "hva"]
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
from typing import Literal, Union
|
|
2
|
-
|
|
3
|
-
import pydantic
|
|
4
|
-
from pydantic import ConfigDict
|
|
5
|
-
|
|
6
|
-
from classiq.interface.chemistry.elements import ELEMENTS
|
|
7
|
-
from classiq.interface.exceptions import ClassiqValueError
|
|
8
|
-
from classiq.interface.helpers.custom_pydantic_types import AtomType
|
|
9
|
-
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
|
10
|
-
HashablePydanticBaseModel,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class Atom(HashablePydanticBaseModel):
|
|
15
|
-
symbol: Literal[tuple(ELEMENTS)] = pydantic.Field(description="The atom symbol") # type: ignore[valid-type]
|
|
16
|
-
x: float = pydantic.Field(description="The x coordinate of the atom")
|
|
17
|
-
y: float = pydantic.Field(description="The y coordinate of the atom")
|
|
18
|
-
z: float = pydantic.Field(description="The z coordinate of the atom")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class Molecule(HashablePydanticBaseModel):
|
|
22
|
-
atoms: list[Atom] = pydantic.Field(
|
|
23
|
-
description="A list of atoms each containing the atoms symbol and its (x,y,z) location",
|
|
24
|
-
min_length=1,
|
|
25
|
-
)
|
|
26
|
-
spin: pydantic.NonNegativeInt = pydantic.Field(
|
|
27
|
-
default=1, description="spin of the molecule"
|
|
28
|
-
)
|
|
29
|
-
charge: pydantic.NonNegativeInt = pydantic.Field(
|
|
30
|
-
default=0, description="charge of the molecule"
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
@property
|
|
34
|
-
def atoms_type(self) -> list[AtomType]:
|
|
35
|
-
return [(atom.symbol, [atom.x, atom.y, atom.z]) for atom in self.atoms]
|
|
36
|
-
|
|
37
|
-
@classmethod
|
|
38
|
-
def _validate_atom(cls, atom: Union[AtomType, Atom]) -> Atom:
|
|
39
|
-
if isinstance(atom, (list, tuple)):
|
|
40
|
-
return cls._validate_old_atoms_type(atom)
|
|
41
|
-
return atom
|
|
42
|
-
|
|
43
|
-
@pydantic.field_validator("atoms", mode="before")
|
|
44
|
-
@classmethod
|
|
45
|
-
def _validate_atoms(cls, atoms: list[Union[AtomType, Atom]]) -> list[Atom]:
|
|
46
|
-
return [cls._validate_atom(atom) for atom in atoms]
|
|
47
|
-
|
|
48
|
-
@staticmethod
|
|
49
|
-
def _validate_old_atoms_type(atom: AtomType) -> Atom:
|
|
50
|
-
if len(atom) != 2:
|
|
51
|
-
raise ClassiqValueError(
|
|
52
|
-
"each atom should be a list of two entries: 1) name pf the elemnt (str) 2) list of its (x,y,z) location"
|
|
53
|
-
)
|
|
54
|
-
if not isinstance(atom[0], str):
|
|
55
|
-
raise ClassiqValueError(
|
|
56
|
-
f"atom name should be a string. unknown element: {atom[0]}."
|
|
57
|
-
)
|
|
58
|
-
if len(atom[1]) != 3:
|
|
59
|
-
raise ClassiqValueError(
|
|
60
|
-
f"location of the atom is of length three, representing the (x,y,z) coordinates of the atom, error value: {atom[1]}"
|
|
61
|
-
)
|
|
62
|
-
for idx in atom[1]:
|
|
63
|
-
if not isinstance(idx, (float, int)):
|
|
64
|
-
raise ClassiqValueError(
|
|
65
|
-
f"coordinates of the atom should be of type float. error value: {idx}"
|
|
66
|
-
)
|
|
67
|
-
symbol, coordinate = atom
|
|
68
|
-
|
|
69
|
-
return Atom(symbol=symbol, x=coordinate[0], y=coordinate[1], z=coordinate[2])
|
|
70
|
-
|
|
71
|
-
model_config = ConfigDict(frozen=True)
|