classiq 0.88.0__py3-none-any.whl → 0.90.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.
Potentially problematic release.
This version of classiq might be problematic. Click here for more details.
- classiq/__init__.py +1 -0
- classiq/_internals/api_wrapper.py +16 -32
- classiq/_internals/config.py +1 -1
- classiq/analyzer/show_interactive_hack.py +26 -1
- classiq/applications/chemistry/chemistry_model_constructor.py +14 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +9 -6
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +16 -8
- classiq/evaluators/classical_expression.py +63 -41
- classiq/evaluators/control.py +31 -52
- classiq/evaluators/expression_evaluator.py +8 -4
- classiq/evaluators/parameter_types.py +200 -104
- classiq/evaluators/qmod_annotated_expression.py +10 -9
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +2 -2
- classiq/evaluators/qmod_expression_visitors/qmod_expression_renamer.py +1 -1
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +66 -5
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +12 -37
- classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +8 -17
- classiq/evaluators/qmod_node_evaluators/measurement_evaluation.py +1 -1
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +7 -1
- classiq/evaluators/qmod_node_evaluators/name_evaluation.py +0 -1
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +9 -1
- classiq/evaluators/qmod_node_evaluators/utils.py +33 -0
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +4 -7
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +2 -26
- classiq/interface/analyzer/result.py +4 -0
- classiq/interface/backend/backend_preferences.py +1 -1
- classiq/interface/chemistry/ground_state_problem.py +16 -2
- classiq/interface/executor/optimizer_preferences.py +0 -112
- classiq/interface/generator/application_apis/chemistry_declarations.py +3 -1
- classiq/interface/generator/arith/arithmetic_expression_validator.py +2 -7
- classiq/interface/generator/arith/register_user_input.py +1 -1
- classiq/interface/generator/expressions/evaluated_expression.py +3 -13
- classiq/interface/generator/expressions/expression_types.py +8 -22
- classiq/interface/generator/expressions/proxies/classical/classical_proxy.py +2 -2
- classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +1 -2
- classiq/interface/generator/functions/classical_type.py +24 -3
- classiq/interface/generator/functions/concrete_types.py +1 -1
- classiq/interface/generator/functions/function_declaration.py +0 -4
- classiq/interface/generator/functions/type_name.py +25 -0
- classiq/interface/generator/generated_circuit_data.py +4 -0
- classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
- classiq/interface/generator/preferences/qasm_to_qmod_params.py +14 -0
- classiq/interface/generator/quantum_function_call.py +3 -3
- classiq/interface/generator/user_defined_function_params.py +0 -3
- classiq/interface/helpers/model_normalizer.py +0 -6
- classiq/interface/ide/ide_data.py +1 -1
- classiq/interface/ide/visual_model.py +3 -2
- classiq/interface/model/block.py +5 -1
- classiq/interface/model/handle_binding.py +2 -2
- classiq/interface/model/port_declaration.py +2 -1
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +16 -12
- classiq/interface/model/quantum_lambda_function.py +1 -1
- classiq/interface/model/quantum_statement.py +2 -4
- classiq/interface/model/quantum_type.py +47 -4
- classiq/interface/server/routes.py +2 -3
- classiq/model_expansions/atomic_expression_functions_defs.py +4 -22
- classiq/model_expansions/capturing/captured_vars.py +7 -3
- classiq/model_expansions/closure.py +8 -0
- classiq/model_expansions/interpreters/base_interpreter.py +84 -22
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +1 -1
- classiq/model_expansions/interpreters/generative_interpreter.py +7 -5
- classiq/model_expansions/quantum_operations/allocate.py +92 -21
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +28 -27
- classiq/model_expansions/quantum_operations/call_emitter.py +32 -26
- classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -2
- classiq/model_expansions/quantum_operations/emitter.py +39 -69
- classiq/model_expansions/quantum_operations/expression_evaluator.py +13 -2
- classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -5
- classiq/model_expansions/quantum_operations/variable_decleration.py +16 -11
- classiq/model_expansions/scope.py +36 -29
- classiq/model_expansions/scope_initialization.py +3 -6
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +6 -2
- classiq/model_expansions/transformers/model_renamer.py +35 -64
- classiq/model_expansions/transformers/type_modifier_inference.py +6 -6
- classiq/model_expansions/visitors/boolean_expression_transformers.py +7 -31
- classiq/model_expansions/visitors/symbolic_param_inference.py +9 -3
- classiq/open_library/functions/__init__.py +2 -0
- classiq/open_library/functions/state_preparation.py +140 -5
- classiq/qmod/builtins/functions/allocation.py +8 -8
- classiq/qmod/builtins/functions/arithmetic.py +1 -1
- classiq/qmod/builtins/functions/chemistry.py +64 -0
- classiq/qmod/builtins/functions/exponentiation.py +7 -13
- classiq/qmod/builtins/functions/qsvm.py +1 -1
- classiq/qmod/builtins/operations.py +38 -10
- classiq/qmod/generative.py +2 -4
- classiq/qmod/native/pretty_printer.py +1 -1
- classiq/qmod/pretty_print/pretty_printer.py +1 -1
- classiq/qmod/qmod_constant.py +1 -1
- classiq/qmod/qmod_parameter.py +2 -2
- classiq/qmod/qmod_variable.py +62 -16
- classiq/qmod/quantum_expandable.py +1 -1
- classiq/synthesis.py +37 -1
- classiq/visualization.py +1 -1
- {classiq-0.88.0.dist-info → classiq-0.90.0.dist-info}/METADATA +2 -2
- {classiq-0.88.0.dist-info → classiq-0.90.0.dist-info}/RECORD +98 -102
- classiq/evaluators/arg_type_match.py +0 -168
- classiq/evaluators/classical_type_inference.py +0 -121
- classiq/interface/combinatorial_optimization/optimization_problem.py +0 -17
- classiq/interface/combinatorial_optimization/result.py +0 -9
- classiq/model_expansions/transformers/ast_renamer.py +0 -26
- {classiq-0.88.0.dist-info → classiq-0.90.0.dist-info}/WHEEL +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ast
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Callable, Union, cast
|
|
3
3
|
|
|
4
4
|
import sympy
|
|
5
5
|
|
|
@@ -184,37 +184,25 @@ def try_eval_sympy_function(
|
|
|
184
184
|
if not isinstance(sympy_func, sympy.FunctionClass):
|
|
185
185
|
return False
|
|
186
186
|
_validate_no_kwargs(node)
|
|
187
|
-
args: Optional[list[Any]] = None
|
|
188
|
-
sympy_ret_val: Any = None
|
|
189
|
-
if all(expr_val.has_value(arg) for arg in node.args):
|
|
190
|
-
args = [expr_val.get_value(arg) for arg in node.args]
|
|
191
|
-
sympy_ret_val = sympy_func(*args)
|
|
192
|
-
if not isinstance(sympy_ret_val, sympy.Expr):
|
|
193
|
-
raise ClassiqInternalExpansionError
|
|
194
187
|
ret_type: QmodType
|
|
195
|
-
ret_val: Any = None
|
|
196
188
|
if hasattr(sympy_func, "is_Boolean") and sympy_func.is_Boolean:
|
|
197
189
|
ret_type = Bool()
|
|
198
|
-
if args is not None:
|
|
199
|
-
ret_val = bool(sympy_ret_val)
|
|
200
190
|
elif (
|
|
201
191
|
hasattr(sympy_func, "is_Integer") and sympy_func.is_Integer
|
|
202
192
|
) or func_name in INTEGER_FUNCTION_OVERRIDE:
|
|
203
193
|
ret_type = Integer()
|
|
204
|
-
if args is not None:
|
|
205
|
-
ret_val = int(sympy_ret_val)
|
|
206
194
|
else:
|
|
207
195
|
ret_type = Real()
|
|
208
|
-
if sympy_ret_val is not None:
|
|
209
|
-
if sympy_ret_val.is_imaginary:
|
|
210
|
-
ret_val = complex(sympy_ret_val)
|
|
211
|
-
elif sympy_ret_val.is_real:
|
|
212
|
-
ret_val = float(sympy_ret_val)
|
|
213
|
-
else:
|
|
214
|
-
raise ClassiqInternalExpansionError
|
|
215
196
|
expr_val.set_type(node, ret_type)
|
|
216
|
-
|
|
217
|
-
|
|
197
|
+
|
|
198
|
+
if any(not expr_val.has_value(arg) for arg in node.args):
|
|
199
|
+
return True
|
|
200
|
+
|
|
201
|
+
args = [expr_val.get_value(arg) for arg in node.args]
|
|
202
|
+
sympy_ret_val = sympy_func(*args)
|
|
203
|
+
if not isinstance(sympy_ret_val, sympy.Basic):
|
|
204
|
+
raise ClassiqInternalExpansionError
|
|
205
|
+
expr_val.set_value(node, sympy_ret_val)
|
|
218
206
|
return True
|
|
219
207
|
|
|
220
208
|
|
|
@@ -265,14 +253,7 @@ def try_eval_builtin_function(
|
|
|
265
253
|
sympy_val = sympy.mod_inverse(
|
|
266
254
|
*[expr_val.get_value(arg) for arg in node.args]
|
|
267
255
|
)
|
|
268
|
-
|
|
269
|
-
if isinstance(sympy_val, sympy.Expr) and sympy_val.is_imaginary:
|
|
270
|
-
ret_val = complex(sympy_val)
|
|
271
|
-
elif args_are_int:
|
|
272
|
-
ret_val = int(sympy_val)
|
|
273
|
-
else:
|
|
274
|
-
ret_val = float(sympy_val)
|
|
275
|
-
expr_val.set_value(node, ret_val)
|
|
256
|
+
expr_val.set_value(node, sympy_val)
|
|
276
257
|
return True
|
|
277
258
|
|
|
278
259
|
if func_name == "sum":
|
|
@@ -293,13 +274,7 @@ def try_eval_builtin_function(
|
|
|
293
274
|
expr_val.set_type(node, Real())
|
|
294
275
|
if args_have_values:
|
|
295
276
|
sympy_val = sympy.sqrt(*[expr_val.get_value(arg) for arg in node.args])
|
|
296
|
-
|
|
297
|
-
ret_val = complex(sympy_val)
|
|
298
|
-
elif float(sympy_val) == int(sympy_val):
|
|
299
|
-
ret_val = int(sympy_val)
|
|
300
|
-
else:
|
|
301
|
-
ret_val = float(sympy_val)
|
|
302
|
-
expr_val.set_value(node, ret_val)
|
|
277
|
+
expr_val.set_value(node, sympy_val)
|
|
303
278
|
return True
|
|
304
279
|
|
|
305
280
|
if func_name == "abs":
|
|
@@ -16,7 +16,11 @@ from classiq.interface.generator.functions.classical_type import (
|
|
|
16
16
|
from classiq.interface.generator.functions.type_name import Enum
|
|
17
17
|
|
|
18
18
|
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
19
|
-
from classiq.evaluators.qmod_node_evaluators.utils import
|
|
19
|
+
from classiq.evaluators.qmod_node_evaluators.utils import (
|
|
20
|
+
SYMPY_SYMBOLS,
|
|
21
|
+
QmodType,
|
|
22
|
+
get_sympy_type,
|
|
23
|
+
)
|
|
20
24
|
|
|
21
25
|
QMOD_LITERALS: dict[str, tuple[ClassicalType, Any]] = {
|
|
22
26
|
"false": (Bool(), False),
|
|
@@ -68,22 +72,9 @@ def try_eval_qmod_literal(expr_val: QmodAnnotatedExpression, node: ast.Name) ->
|
|
|
68
72
|
|
|
69
73
|
def try_eval_sympy_constant(expr_val: QmodAnnotatedExpression, node: ast.Name) -> bool:
|
|
70
74
|
sympy_val = SYMPY_SYMBOLS.get(node.id)
|
|
71
|
-
if not isinstance(sympy_val, sympy.
|
|
75
|
+
if not isinstance(sympy_val, sympy.Basic) or len(sympy_val.free_symbols) > 0:
|
|
72
76
|
return False
|
|
73
|
-
constant_type
|
|
74
|
-
constant_value: Any
|
|
75
|
-
if sympy_val.is_Integer:
|
|
76
|
-
constant_type = Integer()
|
|
77
|
-
constant_value = int(sympy_val)
|
|
78
|
-
elif sympy_val.is_Boolean:
|
|
79
|
-
constant_type = Bool()
|
|
80
|
-
constant_value = bool(sympy_val)
|
|
81
|
-
elif sympy_val.is_imaginary:
|
|
82
|
-
constant_type = Real()
|
|
83
|
-
constant_value = complex(sympy_val)
|
|
84
|
-
else:
|
|
85
|
-
constant_type = Real()
|
|
86
|
-
constant_value = float(sympy_val)
|
|
77
|
+
constant_type = get_sympy_type(sympy_val)
|
|
87
78
|
expr_val.set_type(node, constant_type)
|
|
88
|
-
expr_val.set_value(node,
|
|
79
|
+
expr_val.set_value(node, sympy_val)
|
|
89
80
|
return True
|
|
@@ -21,5 +21,5 @@ def eval_measurement(expr_val: QmodAnnotatedExpression, node: ast.Call) -> None:
|
|
|
21
21
|
if is_classical_type(arg_type):
|
|
22
22
|
raise ClassiqExpansionError("'measure' expects a quantum input")
|
|
23
23
|
if not isinstance(arg_type, QuantumBit):
|
|
24
|
-
raise ClassiqExpansionError("
|
|
24
|
+
raise ClassiqExpansionError("'measure' only supports QBits")
|
|
25
25
|
expr_val.set_type(node, Bool())
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import ast
|
|
2
2
|
|
|
3
|
+
import sympy
|
|
4
|
+
|
|
3
5
|
from classiq.interface.exceptions import (
|
|
4
6
|
ClassiqExpansionError,
|
|
5
7
|
ClassiqInternalExpansionError,
|
|
@@ -84,7 +86,11 @@ def eval_min_max_op(
|
|
|
84
86
|
|
|
85
87
|
if all(expr_val.has_value(arg) for arg in node.args):
|
|
86
88
|
values = [expr_val.get_value(arg) for arg in node.args]
|
|
87
|
-
if not all(
|
|
89
|
+
if not all(
|
|
90
|
+
isinstance(value, (int, float))
|
|
91
|
+
or (isinstance(value, sympy.Expr) and value.is_real)
|
|
92
|
+
for value in values
|
|
93
|
+
):
|
|
88
94
|
raise ClassiqExpansionError(f"Invalid argument for function {func_name!r}")
|
|
89
95
|
|
|
90
96
|
if func_name == "min":
|
|
@@ -22,7 +22,6 @@ from classiq.evaluators.qmod_type_inference.classical_type_inference import (
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def eval_name(expr_val: QmodAnnotatedExpression, node: ast.Name, value: Any) -> None:
|
|
25
|
-
# FIXME: Remove sympy compatibility (CLS-3214)
|
|
26
25
|
if isinstance(
|
|
27
26
|
value, (bool, int, float, complex, list, QmodStructInstance, sympy.Basic)
|
|
28
27
|
):
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import ast
|
|
2
2
|
from typing import TYPE_CHECKING, Optional
|
|
3
3
|
|
|
4
|
+
import sympy
|
|
5
|
+
|
|
4
6
|
from classiq.interface.exceptions import ClassiqExpansionError
|
|
5
7
|
from classiq.interface.generator.functions.classical_type import Bool
|
|
6
8
|
from classiq.interface.model.quantum_type import QuantumScalar
|
|
7
9
|
|
|
8
10
|
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
9
|
-
from classiq.evaluators.qmod_node_evaluators.utils import
|
|
11
|
+
from classiq.evaluators.qmod_node_evaluators.utils import (
|
|
12
|
+
QmodType,
|
|
13
|
+
get_sympy_val,
|
|
14
|
+
is_classical_type,
|
|
15
|
+
)
|
|
10
16
|
from classiq.model_expansions.arithmetic import NumericAttributes
|
|
11
17
|
|
|
12
18
|
|
|
@@ -46,6 +52,8 @@ def get_classical_value_for_arithmetic(
|
|
|
46
52
|
return None
|
|
47
53
|
|
|
48
54
|
value = expr_val.get_value(node)
|
|
55
|
+
if isinstance(value, sympy.Basic):
|
|
56
|
+
value = get_sympy_val(value)
|
|
49
57
|
if not isinstance(value, (int, float)):
|
|
50
58
|
if treat_qnum_as_float and isinstance(value, complex):
|
|
51
59
|
return None
|
|
@@ -4,6 +4,7 @@ import sympy
|
|
|
4
4
|
|
|
5
5
|
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
|
6
6
|
from classiq.interface.generator.functions.classical_type import (
|
|
7
|
+
Bool,
|
|
7
8
|
ClassicalArray,
|
|
8
9
|
ClassicalTuple,
|
|
9
10
|
ClassicalType,
|
|
@@ -100,3 +101,35 @@ def is_classical_integer(qmod_type: QmodType) -> bool:
|
|
|
100
101
|
return isinstance(qmod_type, Integer) or (
|
|
101
102
|
isinstance(qmod_type, TypeName) and qmod_type.is_enum
|
|
102
103
|
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def get_sympy_val(val: sympy.Basic) -> Union[bool, int, float, complex]:
|
|
107
|
+
if hasattr(val, "is_Boolean") and val.is_Boolean:
|
|
108
|
+
return bool(val)
|
|
109
|
+
if (hasattr(val, "is_integer") and val.is_integer) or (
|
|
110
|
+
hasattr(val, "is_Integer") and val.is_Integer
|
|
111
|
+
):
|
|
112
|
+
return int(val)
|
|
113
|
+
if hasattr(val, "is_real") and val.is_real:
|
|
114
|
+
return float(val)
|
|
115
|
+
if (hasattr(val, "is_complex") and val.is_complex) or (
|
|
116
|
+
hasattr(val, "is_imaginary") and val.is_imaginary
|
|
117
|
+
):
|
|
118
|
+
return complex(val)
|
|
119
|
+
raise ClassiqInternalExpansionError("Unidentified sympy value")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def get_sympy_type(val: sympy.Basic) -> ClassicalType:
|
|
123
|
+
if hasattr(val, "is_Boolean") and val.is_Boolean:
|
|
124
|
+
return Bool()
|
|
125
|
+
if (hasattr(val, "is_integer") and val.is_integer) or (
|
|
126
|
+
hasattr(val, "is_Integer") and val.is_Integer
|
|
127
|
+
):
|
|
128
|
+
return Integer()
|
|
129
|
+
if (
|
|
130
|
+
(hasattr(val, "is_real") and val.is_real)
|
|
131
|
+
or (hasattr(val, "is_complex") and val.is_complex)
|
|
132
|
+
or (hasattr(val, "is_imaginary") and val.is_imaginary)
|
|
133
|
+
):
|
|
134
|
+
return Real()
|
|
135
|
+
raise ClassiqInternalExpansionError("Unidentified sympy value")
|
|
@@ -20,6 +20,8 @@ from classiq.interface.generator.functions.type_name import Enum, Struct, TypeNa
|
|
|
20
20
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
|
21
21
|
from classiq.interface.helpers.backward_compatibility import zip_strict
|
|
22
22
|
|
|
23
|
+
from classiq.evaluators.qmod_node_evaluators.utils import get_sympy_type
|
|
24
|
+
|
|
23
25
|
|
|
24
26
|
def _copy_generative_flag(
|
|
25
27
|
from_type: ClassicalType, to_type: Optional[ClassicalType]
|
|
@@ -57,13 +59,8 @@ def infer_classical_type(value: Any) -> ClassicalType:
|
|
|
57
59
|
)
|
|
58
60
|
)
|
|
59
61
|
return classical_type
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
isinstance(value, sympy.Basic)
|
|
63
|
-
and len(value.free_symbols) == 0
|
|
64
|
-
and value.is_complex
|
|
65
|
-
):
|
|
66
|
-
return Real()
|
|
62
|
+
if isinstance(value, sympy.Basic):
|
|
63
|
+
return get_sympy_type(value)
|
|
67
64
|
raise ClassiqInternalExpansionError
|
|
68
65
|
|
|
69
66
|
|
classiq/interface/_version.py
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
from typing import Annotated, Optional
|
|
2
2
|
|
|
3
|
-
import numpy
|
|
4
3
|
import pydantic
|
|
5
|
-
from pydantic import
|
|
4
|
+
from pydantic import Field, StringConstraints
|
|
6
5
|
|
|
7
6
|
from classiq.interface.backend.quantum_backend_providers import AnalyzerProviderVendor
|
|
8
|
-
from classiq.interface.chemistry.ground_state_problem import MoleculeProblem
|
|
9
|
-
from classiq.interface.executor.optimizer_preferences import OptimizerPreferences
|
|
10
7
|
from classiq.interface.generator.hardware.hardware_data import SynthesisHardwareData
|
|
11
8
|
from classiq.interface.generator.model.preferences.preferences import (
|
|
12
9
|
TranspilationOption,
|
|
@@ -80,7 +77,7 @@ class AnalysisHardwareListParams(AnalysisParams, HardwareListParams):
|
|
|
80
77
|
|
|
81
78
|
|
|
82
79
|
class HardwareParams(pydantic.BaseModel):
|
|
83
|
-
device: PydanticNonEmptyString = pydantic.Field(default=None, description="Devices")
|
|
80
|
+
device: PydanticNonEmptyString = pydantic.Field(default=None, description="Devices") # type: ignore[assignment]
|
|
84
81
|
provider: AnalyzerProviderVendor
|
|
85
82
|
|
|
86
83
|
|
|
@@ -103,24 +100,3 @@ class AnalysisRBParams(pydantic.BaseModel):
|
|
|
103
100
|
num_clifford: list[
|
|
104
101
|
Annotated[int, Annotated[int, Field(strict=True, gt=0, le=MAX_NUM_CLIFFORD)]]
|
|
105
102
|
]
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class ChemistryGenerationParams(pydantic.BaseModel):
|
|
109
|
-
model_config = ConfigDict(title="Chemistry")
|
|
110
|
-
|
|
111
|
-
molecule: MoleculeProblem = pydantic.Field(
|
|
112
|
-
title="Molecule",
|
|
113
|
-
default=...,
|
|
114
|
-
description="The molecule to generate the VQE ansatz for",
|
|
115
|
-
)
|
|
116
|
-
optimizer_preferences: OptimizerPreferences = pydantic.Field(
|
|
117
|
-
default=..., description="Execution options for the classical Optimizer"
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
def initial_point(self) -> Optional[numpy.ndarray]:
|
|
121
|
-
if self.optimizer_preferences.initial_point is not None:
|
|
122
|
-
return numpy.ndarray(
|
|
123
|
-
self.optimizer_preferences.initial_point # type: ignore[arg-type]
|
|
124
|
-
)
|
|
125
|
-
else:
|
|
126
|
-
return None
|
|
@@ -40,6 +40,10 @@ class QasmCode(pydantic.BaseModel):
|
|
|
40
40
|
code: str = Field(..., max_length=MAX_FILE_LENGTH)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
class QmodCode(VersionedModel):
|
|
44
|
+
code: str = Field(..., max_length=MAX_FILE_LENGTH)
|
|
45
|
+
|
|
46
|
+
|
|
43
47
|
class AnalysisStatus(StrEnum):
|
|
44
48
|
NONE = "none"
|
|
45
49
|
SUCCESS = "success"
|
|
@@ -274,7 +274,7 @@ class AzureCredential(BaseSettings):
|
|
|
274
274
|
|
|
275
275
|
def __init__(self, **data: Any) -> None:
|
|
276
276
|
initial_data = {
|
|
277
|
-
field: data[field] for field in data if field in self.model_fields
|
|
277
|
+
field: data[field] for field in data if field in self.__class__.model_fields
|
|
278
278
|
}
|
|
279
279
|
super().__init__(**data)
|
|
280
280
|
for field, value in initial_data.items():
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import warnings
|
|
2
|
+
from typing import Annotated, Any, Literal, Optional, Union, cast
|
|
2
3
|
|
|
3
4
|
import pydantic
|
|
4
5
|
from pydantic import ConfigDict, Field
|
|
@@ -7,7 +8,7 @@ from pydantic_core.core_schema import ValidationInfo
|
|
|
7
8
|
from classiq.interface.chemistry.fermionic_operator import SummedFermionicOperator
|
|
8
9
|
from classiq.interface.chemistry.molecule import Molecule
|
|
9
10
|
from classiq.interface.enum_utils import StrEnum
|
|
10
|
-
from classiq.interface.exceptions import ClassiqValueError
|
|
11
|
+
from classiq.interface.exceptions import ClassiqDeprecationWarning, ClassiqValueError
|
|
11
12
|
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
|
12
13
|
HashablePydanticBaseModel,
|
|
13
14
|
)
|
|
@@ -52,6 +53,19 @@ class GroundStateProblem(HashablePydanticBaseModel):
|
|
|
52
53
|
)
|
|
53
54
|
num_qubits: Optional[int] = pydantic.Field(default=None)
|
|
54
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
|
+
|
|
55
69
|
@pydantic.field_validator("z2_symmetries")
|
|
56
70
|
@classmethod
|
|
57
71
|
def _validate_z2_symmetries(cls, z2_symmetries: bool, info: ValidationInfo) -> bool:
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
|
-
import pydantic
|
|
4
|
-
from pydantic import BaseModel
|
|
5
|
-
from pydantic_core.core_schema import ValidationInfo
|
|
6
|
-
|
|
7
1
|
from classiq.interface.enum_utils import StrEnum
|
|
8
|
-
from classiq.interface.exceptions import ClassiqValueError
|
|
9
|
-
from classiq.interface.helpers.custom_pydantic_types import PydanticAlphaParamCVAR
|
|
10
2
|
|
|
11
3
|
|
|
12
4
|
class CostType(StrEnum):
|
|
@@ -22,107 +14,3 @@ class OptimizerType(StrEnum):
|
|
|
22
14
|
NELDER_MEAD = "NELDER_MEAD"
|
|
23
15
|
ADAM = "ADAM"
|
|
24
16
|
SLSQP = "SLSQP"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class OptimizerPreferences(BaseModel):
|
|
28
|
-
name: OptimizerType = pydantic.Field(
|
|
29
|
-
default=OptimizerType.COBYLA, description="Classical optimization algorithm."
|
|
30
|
-
)
|
|
31
|
-
num_shots: Optional[pydantic.PositiveInt] = pydantic.Field(
|
|
32
|
-
default=None,
|
|
33
|
-
description="Number of repetitions of the quantum ansatz.",
|
|
34
|
-
)
|
|
35
|
-
max_iteration: pydantic.PositiveInt = pydantic.Field(
|
|
36
|
-
default=100, description="Maximal number of optimizer iterations"
|
|
37
|
-
)
|
|
38
|
-
tolerance: Optional[pydantic.PositiveFloat] = pydantic.Field(
|
|
39
|
-
default=None, description="Final accuracy in the optimization"
|
|
40
|
-
)
|
|
41
|
-
step_size: Optional[pydantic.PositiveFloat] = pydantic.Field(
|
|
42
|
-
default=None,
|
|
43
|
-
description="step size for numerically " "calculating the gradient",
|
|
44
|
-
)
|
|
45
|
-
random_seed: Optional[int] = pydantic.Field(
|
|
46
|
-
default=None,
|
|
47
|
-
description="The random seed used for the generation",
|
|
48
|
-
)
|
|
49
|
-
initial_point: Optional[list[float]] = pydantic.Field(
|
|
50
|
-
default=None,
|
|
51
|
-
description="Initial values for the ansatz parameters",
|
|
52
|
-
)
|
|
53
|
-
skip_compute_variance: bool = pydantic.Field(
|
|
54
|
-
default=False,
|
|
55
|
-
description="If True, the optimizer will not compute the variance of the ansatz.",
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
@pydantic.field_validator("tolerance", mode="before")
|
|
59
|
-
@classmethod
|
|
60
|
-
def check_tolerance(
|
|
61
|
-
cls, tolerance: Optional[pydantic.PositiveFloat], info: ValidationInfo
|
|
62
|
-
) -> Optional[pydantic.PositiveFloat]:
|
|
63
|
-
optimizer_type = info.data.get("type")
|
|
64
|
-
if tolerance is not None and optimizer_type == OptimizerType.SPSA:
|
|
65
|
-
raise ClassiqValueError("No tolerance param for SPSA optimizer")
|
|
66
|
-
|
|
67
|
-
if tolerance is None and optimizer_type != OptimizerType.SPSA:
|
|
68
|
-
tolerance = pydantic.PositiveFloat(0.001)
|
|
69
|
-
|
|
70
|
-
return tolerance
|
|
71
|
-
|
|
72
|
-
@pydantic.field_validator("step_size", mode="before")
|
|
73
|
-
@classmethod
|
|
74
|
-
def check_step_size(
|
|
75
|
-
cls, step_size: Optional[pydantic.PositiveFloat], info: ValidationInfo
|
|
76
|
-
) -> Optional[pydantic.PositiveFloat]:
|
|
77
|
-
optimizer_type = info.data.get("name")
|
|
78
|
-
if step_size is not None and optimizer_type not in (
|
|
79
|
-
OptimizerType.L_BFGS_B,
|
|
80
|
-
OptimizerType.ADAM,
|
|
81
|
-
):
|
|
82
|
-
raise ClassiqValueError(
|
|
83
|
-
"Use step_size only for L_BFGS_B or ADAM optimizers."
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
if step_size is None and optimizer_type in (
|
|
87
|
-
OptimizerType.L_BFGS_B,
|
|
88
|
-
OptimizerType.ADAM,
|
|
89
|
-
):
|
|
90
|
-
step_size = pydantic.PositiveFloat(0.05)
|
|
91
|
-
|
|
92
|
-
return step_size
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
class GroundStateOptimizer(OptimizerPreferences):
|
|
96
|
-
pass
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class CombinatorialOptimizer(OptimizerPreferences):
|
|
100
|
-
cost_type: CostType = pydantic.Field(
|
|
101
|
-
default=CostType.CVAR,
|
|
102
|
-
description="Summarizing method of the measured bit strings",
|
|
103
|
-
)
|
|
104
|
-
alpha_cvar: Optional[PydanticAlphaParamCVAR] = pydantic.Field(
|
|
105
|
-
default=None, description="Parameter for the CVAR summarizing method"
|
|
106
|
-
)
|
|
107
|
-
is_maximization: bool = pydantic.Field(
|
|
108
|
-
default=False,
|
|
109
|
-
description="Whether the optimization goal is to maximize",
|
|
110
|
-
)
|
|
111
|
-
should_check_valid_solutions: bool = pydantic.Field(
|
|
112
|
-
default=False,
|
|
113
|
-
description="Whether to check if all the solutions satisfy the constraints",
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
@pydantic.field_validator("alpha_cvar", mode="before")
|
|
117
|
-
@classmethod
|
|
118
|
-
def check_alpha_cvar(
|
|
119
|
-
cls, alpha_cvar: Optional[PydanticAlphaParamCVAR], info: ValidationInfo
|
|
120
|
-
) -> Optional[PydanticAlphaParamCVAR]:
|
|
121
|
-
cost_type = info.data.get("cost_type")
|
|
122
|
-
if alpha_cvar is not None and cost_type != CostType.CVAR:
|
|
123
|
-
raise ClassiqValueError("Use CVAR params only for CostType.CVAR.")
|
|
124
|
-
|
|
125
|
-
if alpha_cvar is None and cost_type == CostType.CVAR:
|
|
126
|
-
alpha_cvar = PydanticAlphaParamCVAR(0.2)
|
|
127
|
-
|
|
128
|
-
return alpha_cvar
|
|
@@ -20,7 +20,9 @@ FOCK_HAMILTONIAN_PROBLEM_PARAM = ClassicalParameterDeclaration(
|
|
|
20
20
|
name="fock_hamiltonian_problem",
|
|
21
21
|
classical_type=Struct(name="FockHamiltonianProblem"),
|
|
22
22
|
)
|
|
23
|
-
FOCK_HAMILTONIAN_SIZE =
|
|
23
|
+
FOCK_HAMILTONIAN_SIZE = (
|
|
24
|
+
"fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0].pauli.len"
|
|
25
|
+
)
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
class ChemistryProblemType(Enum):
|
|
@@ -88,13 +88,8 @@ class ExpressionValidator(ast.NodeVisitor):
|
|
|
88
88
|
ast_expr = ast.parse(adjusted_expression, filename="", mode=self._mode)
|
|
89
89
|
except SyntaxError as e:
|
|
90
90
|
raise ClassiqValueError(f"Failed to parse expression {expression!r}") from e
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
self.visit(self._ast_obj)
|
|
94
|
-
except RecursionError as e:
|
|
95
|
-
raise ClassiqValueError(
|
|
96
|
-
f"Failed to parse expression since it is too long: {expression}"
|
|
97
|
-
) from e
|
|
91
|
+
self._ast_obj = self.rewrite_ast(ast_expr)
|
|
92
|
+
self.visit(self._ast_obj)
|
|
98
93
|
|
|
99
94
|
@staticmethod
|
|
100
95
|
def _get_adjusted_expression(expression: str) -> str:
|
|
@@ -19,7 +19,7 @@ class RegisterArithmeticInfo(HashablePydanticBaseModel):
|
|
|
19
19
|
is_signed: bool = pydantic.Field(default=False)
|
|
20
20
|
fraction_places: pydantic.NonNegativeInt = pydantic.Field(default=0)
|
|
21
21
|
bypass_bounds_validation: bool = pydantic.Field(default=False)
|
|
22
|
-
bounds: PydanticFloatTuple = pydantic.Field(
|
|
22
|
+
bounds: PydanticFloatTuple = pydantic.Field( # type: ignore[assignment]
|
|
23
23
|
default=None,
|
|
24
24
|
validate_default=True,
|
|
25
25
|
)
|
|
@@ -10,10 +10,11 @@ from classiq.interface.backend.pydantic_backend import EXECUTION_PARAMETER_PATTE
|
|
|
10
10
|
from classiq.interface.exceptions import ClassiqValueError
|
|
11
11
|
from classiq.interface.generator.expressions.expression_types import (
|
|
12
12
|
ExpressionValue,
|
|
13
|
-
QmodStructInstance,
|
|
14
13
|
RuntimeConstant,
|
|
15
14
|
)
|
|
16
|
-
from classiq.interface.generator.expressions.
|
|
15
|
+
from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
|
|
16
|
+
QmodStructInstance,
|
|
17
|
+
)
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
@dataclass(frozen=True)
|
|
@@ -21,9 +22,6 @@ class EvaluatedExpression:
|
|
|
21
22
|
value: ExpressionValue
|
|
22
23
|
|
|
23
24
|
def is_constant(self, constant_type: Optional[type] = None) -> bool:
|
|
24
|
-
if self.value is None:
|
|
25
|
-
return False
|
|
26
|
-
|
|
27
25
|
return isinstance(
|
|
28
26
|
self.value,
|
|
29
27
|
get_args(RuntimeConstant) if constant_type is None else constant_type,
|
|
@@ -49,14 +47,6 @@ class EvaluatedExpression:
|
|
|
49
47
|
def to_list(self) -> list:
|
|
50
48
|
return self.as_constant_type(list)
|
|
51
49
|
|
|
52
|
-
def to_handle(self) -> HandleIdentifier:
|
|
53
|
-
if not isinstance(self.value, HandleIdentifier):
|
|
54
|
-
raise ClassiqValueError(
|
|
55
|
-
f"Invalid access to expression {self.value} as HandleIdentifier"
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
return self.value
|
|
59
|
-
|
|
60
50
|
def to_struct_dict(self) -> Mapping[str, Any]:
|
|
61
51
|
if not isinstance(self.value, QmodStructInstance):
|
|
62
52
|
raise ClassiqValueError(
|
|
@@ -1,35 +1,21 @@
|
|
|
1
|
-
from typing import Union
|
|
1
|
+
from typing import TYPE_CHECKING, Union
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
from sympy.logic.boolalg import Boolean
|
|
3
|
+
import sympy
|
|
5
4
|
|
|
6
|
-
from classiq.interface.generator.expressions.handle_identifier import HandleIdentifier
|
|
7
|
-
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
|
8
|
-
AnyClassicalValue,
|
|
9
|
-
)
|
|
10
|
-
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
|
11
|
-
ClassicalProxy,
|
|
12
|
-
)
|
|
13
5
|
from classiq.interface.generator.expressions.proxies.classical.qmod_struct_instance import (
|
|
14
6
|
QmodStructInstance,
|
|
15
7
|
)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
from classiq.interface.generator.expressions.type_proxy import TypeProxy
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
20
11
|
|
|
21
12
|
RuntimeConstant = Union[
|
|
22
13
|
int,
|
|
23
14
|
float,
|
|
24
15
|
list,
|
|
25
16
|
bool,
|
|
17
|
+
complex,
|
|
26
18
|
QmodStructInstance,
|
|
27
|
-
|
|
28
|
-
HandleIdentifier,
|
|
29
|
-
]
|
|
30
|
-
Proxies = Union[
|
|
31
|
-
QmodSizedProxy,
|
|
32
|
-
ClassicalProxy,
|
|
19
|
+
sympy.Basic,
|
|
33
20
|
]
|
|
34
|
-
|
|
35
|
-
ExpressionValue = Union[RuntimeConstant, Proxies, RuntimeExpression]
|
|
21
|
+
ExpressionValue = Union[RuntimeConstant, "QmodAnnotatedExpression"]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections.abc import Mapping
|
|
2
|
-
from typing import TYPE_CHECKING
|
|
2
|
+
from typing import TYPE_CHECKING, Union
|
|
3
3
|
|
|
4
4
|
if TYPE_CHECKING:
|
|
5
5
|
from classiq.interface.generator.expressions.expression_types import ExpressionValue
|
|
@@ -18,7 +18,7 @@ class ClassicalProxy:
|
|
|
18
18
|
return str(self.handle)
|
|
19
19
|
|
|
20
20
|
@property
|
|
21
|
-
def fields(self) -> Mapping[str, "ExpressionValue"]:
|
|
21
|
+
def fields(self) -> Mapping[str, Union["ExpressionValue", "ClassicalProxy"]]:
|
|
22
22
|
raise NotImplementedError
|
|
23
23
|
|
|
24
24
|
@property
|
|
@@ -8,7 +8,6 @@ from classiq.interface.generator.expressions.proxies.classical.classical_proxy i
|
|
|
8
8
|
from classiq.interface.model.handle_binding import FieldHandleBinding, HandleBinding
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
-
from classiq.interface.generator.expressions.expression_types import ExpressionValue
|
|
12
11
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
|
13
12
|
|
|
14
13
|
|
|
@@ -22,7 +21,7 @@ class ClassicalStructProxy(NonSymbolicExpr, ClassicalProxy):
|
|
|
22
21
|
return self._decl
|
|
23
22
|
|
|
24
23
|
@property
|
|
25
|
-
def fields(self) -> Mapping[str,
|
|
24
|
+
def fields(self) -> Mapping[str, ClassicalProxy]:
|
|
26
25
|
return {
|
|
27
26
|
field_name: field_type.get_classical_proxy(
|
|
28
27
|
FieldHandleBinding(base_handle=self.handle, field=field_name)
|