classiq 0.89.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/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 +3 -1
- 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 +1 -25
- classiq/interface/analyzer/result.py +4 -0
- 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/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/concrete_types.py +1 -1
- classiq/interface/generator/generated_circuit_data.py +4 -0
- classiq/interface/generator/preferences/qasm_to_qmod_params.py +14 -0
- classiq/interface/helpers/model_normalizer.py +0 -6
- classiq/interface/ide/visual_model.py +1 -0
- classiq/interface/model/handle_binding.py +1 -1
- classiq/interface/model/port_declaration.py +2 -1
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +16 -12
- classiq/interface/model/quantum_type.py +1 -1
- 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/state_preparation.py +3 -3
- 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 +15 -15
- classiq/qmod/quantum_expandable.py +1 -1
- classiq/synthesis.py +37 -1
- classiq/visualization.py +1 -1
- {classiq-0.89.0.dist-info → classiq-0.90.0.dist-info}/METADATA +1 -1
- {classiq-0.89.0.dist-info → classiq-0.90.0.dist-info}/RECORD +81 -85
- 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.89.0.dist-info → classiq-0.90.0.dist-info}/WHEEL +0 -0
|
@@ -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,
|
|
@@ -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"
|
|
@@ -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:
|
|
@@ -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)
|
|
@@ -47,7 +47,7 @@ PythonClassicalPydanticTypes = (Enum,)
|
|
|
47
47
|
|
|
48
48
|
ConcreteQuantumType = Annotated[
|
|
49
49
|
Union[QuantumBit, QuantumBitvector, QuantumNumeric, TypeName],
|
|
50
|
-
Field(discriminator="kind"
|
|
50
|
+
Field(discriminator="kind"),
|
|
51
51
|
]
|
|
52
52
|
QuantumBitvector.model_rebuild()
|
|
53
53
|
TypeName.model_rebuild()
|
|
@@ -17,6 +17,7 @@ from classiq.interface.generator.register_role import RegisterRole
|
|
|
17
17
|
from classiq.interface.generator.synthesis_metadata.synthesis_execution_data import (
|
|
18
18
|
ExecutionData,
|
|
19
19
|
)
|
|
20
|
+
from classiq.interface.model.block import Block
|
|
20
21
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
21
22
|
ArithmeticOperationKind,
|
|
22
23
|
)
|
|
@@ -210,10 +211,13 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
|
210
211
|
)
|
|
211
212
|
name_with_suffix = self.add_suffix_from_generated_name(generated_name, name)
|
|
212
213
|
return name_with_suffix
|
|
214
|
+
if isinstance(back_ref, Block) and back_ref.label is not None:
|
|
215
|
+
return back_ref.label
|
|
213
216
|
|
|
214
217
|
statement_kind: str = back_ref.kind
|
|
215
218
|
if isinstance(back_ref, ArithmeticOperation):
|
|
216
219
|
statement_kind = back_ref.operation_kind.value
|
|
220
|
+
|
|
217
221
|
return self.add_suffix_from_generated_name(
|
|
218
222
|
generated_name, STATEMENTS_NAME[statement_kind]
|
|
219
223
|
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
from classiq.interface.analyzer.result import QasmCode
|
|
4
|
+
from classiq.interface.enum_utils import StrEnum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class QmodFormat(StrEnum):
|
|
8
|
+
NATIVE = "native"
|
|
9
|
+
PYTHON = "python"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class QasmToQmodParams(BaseModel):
|
|
13
|
+
qasm: QasmCode
|
|
14
|
+
qmod_format: QmodFormat
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import ast
|
|
2
1
|
from typing import Any
|
|
3
2
|
|
|
4
3
|
from classiq.interface.ast_node import ASTNode
|
|
@@ -10,8 +9,6 @@ from classiq.interface.generator.visitor import Transformer, Visitor
|
|
|
10
9
|
from classiq.interface.model.model import Model
|
|
11
10
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
|
12
11
|
|
|
13
|
-
from classiq.model_expansions.transformers.model_renamer import ExprNormalizer
|
|
14
|
-
|
|
15
12
|
|
|
16
13
|
class ModelNormalizer(Visitor):
|
|
17
14
|
def visit(self, node: Any) -> None:
|
|
@@ -28,9 +25,6 @@ class ModelNormalizer(Visitor):
|
|
|
28
25
|
model.functions.sort(key=lambda x: x.name)
|
|
29
26
|
self.generic_visit(model)
|
|
30
27
|
|
|
31
|
-
def visit_Expression(self, expr: Expression) -> None:
|
|
32
|
-
expr.expr = ast.unparse(ExprNormalizer().visit(ast.parse(expr.expr)))
|
|
33
|
-
|
|
34
28
|
def visit_AnonPortDeclaration(self, decl: AnonPortDeclaration) -> None:
|
|
35
29
|
decl.type_modifier = TypeModifier.Mutable
|
|
36
30
|
|
|
@@ -171,6 +171,7 @@ class Operation(pydantic.BaseModel):
|
|
|
171
171
|
expanded: bool = pydantic.Field(default=False)
|
|
172
172
|
show_expanded_label: bool = pydantic.Field(default=False)
|
|
173
173
|
is_low_level_fallback: bool = pydantic.Field(default=False)
|
|
174
|
+
is_measurement: bool = pydantic.Field(default=False)
|
|
174
175
|
|
|
175
176
|
model_config = ConfigDict(frozen=True)
|
|
176
177
|
|
|
@@ -349,7 +349,7 @@ class FieldHandleBinding(NestedHandleBinding):
|
|
|
349
349
|
|
|
350
350
|
@property
|
|
351
351
|
def qmod_expr(self) -> str:
|
|
352
|
-
return f"
|
|
352
|
+
return f"{self.base_handle.qmod_expr}.{self.field}"
|
|
353
353
|
|
|
354
354
|
@property
|
|
355
355
|
def identifier(self) -> str:
|
|
@@ -13,10 +13,11 @@ from classiq.interface.generator.functions.type_modifier import (
|
|
|
13
13
|
)
|
|
14
14
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
|
15
15
|
from classiq.interface.model.parameter import Parameter
|
|
16
|
+
from classiq.interface.model.quantum_type import QuantumBitvector
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class AnonPortDeclaration(Parameter):
|
|
19
|
-
quantum_type: ConcreteQuantumType
|
|
20
|
+
quantum_type: ConcreteQuantumType = pydantic.Field(default_factory=QuantumBitvector)
|
|
20
21
|
direction: PortDeclarationDirection
|
|
21
22
|
kind: Literal["PortDeclaration"]
|
|
22
23
|
type_modifier: TypeModifier
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
from collections.abc import Mapping, Sequence
|
|
2
|
-
from typing import Literal
|
|
3
|
-
|
|
4
|
-
from pydantic import PrivateAttr
|
|
2
|
+
from typing import Literal, cast
|
|
5
3
|
|
|
6
4
|
from classiq.interface.enum_utils import StrEnum
|
|
7
5
|
from classiq.interface.generator.arith.arithmetic import (
|
|
8
6
|
ARITHMETIC_EXPRESSION_RESULT_NAME,
|
|
9
|
-
compute_arithmetic_result_type,
|
|
10
7
|
)
|
|
11
8
|
from classiq.interface.model.handle_binding import (
|
|
12
9
|
ConcreteHandleBinding,
|
|
@@ -18,6 +15,9 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
|
18
15
|
from classiq.interface.model.quantum_statement import HandleMetadata
|
|
19
16
|
from classiq.interface.model.quantum_type import QuantumType
|
|
20
17
|
|
|
18
|
+
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
19
|
+
from classiq.model_expansions.arithmetic import NumericAttributes
|
|
20
|
+
|
|
21
21
|
|
|
22
22
|
class ArithmeticOperationKind(StrEnum):
|
|
23
23
|
InplaceAdd = "inplace_add"
|
|
@@ -29,7 +29,7 @@ class ArithmeticOperation(QuantumAssignmentOperation):
|
|
|
29
29
|
kind: Literal["ArithmeticOperation"]
|
|
30
30
|
|
|
31
31
|
operation_kind: ArithmeticOperationKind
|
|
32
|
-
|
|
32
|
+
classical_assignment: bool = False
|
|
33
33
|
|
|
34
34
|
@property
|
|
35
35
|
def is_inplace(self) -> bool:
|
|
@@ -44,16 +44,20 @@ class ArithmeticOperation(QuantumAssignmentOperation):
|
|
|
44
44
|
machine_precision: int,
|
|
45
45
|
) -> None:
|
|
46
46
|
super().initialize_var_types(var_types, machine_precision)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
expr_val = self.expression.value.value
|
|
48
|
+
if isinstance(expr_val, QmodAnnotatedExpression):
|
|
49
|
+
self._result_type = expr_val.get_quantum_type(expr_val.root)
|
|
50
|
+
else:
|
|
51
|
+
self._result_type = NumericAttributes.from_constant(
|
|
52
|
+
cast(float, expr_val), machine_precision
|
|
53
|
+
).to_quantum_numeric()
|
|
50
54
|
|
|
51
55
|
@property
|
|
52
56
|
def wiring_inouts(
|
|
53
57
|
self,
|
|
54
58
|
) -> Mapping[str, ConcreteHandleBinding]:
|
|
55
59
|
inouts = dict(super().wiring_inouts)
|
|
56
|
-
if self.is_inplace and not self.
|
|
60
|
+
if self.is_inplace and not self.classical_assignment:
|
|
57
61
|
inouts[self.result_name()] = self.result_var
|
|
58
62
|
return inouts
|
|
59
63
|
|
|
@@ -63,7 +67,7 @@ class ArithmeticOperation(QuantumAssignmentOperation):
|
|
|
63
67
|
HandleMetadata(handle=handle, readable_location="in an expression")
|
|
64
68
|
for handle in self.var_handles
|
|
65
69
|
]
|
|
66
|
-
if self.is_inplace and not self.
|
|
70
|
+
if self.is_inplace and not self.classical_assignment:
|
|
67
71
|
inouts.append(
|
|
68
72
|
HandleMetadata(
|
|
69
73
|
handle=self.result_var,
|
|
@@ -74,13 +78,13 @@ class ArithmeticOperation(QuantumAssignmentOperation):
|
|
|
74
78
|
|
|
75
79
|
@property
|
|
76
80
|
def wiring_outputs(self) -> Mapping[str, HandleBinding]:
|
|
77
|
-
if self.is_inplace or self.
|
|
81
|
+
if self.is_inplace or self.classical_assignment:
|
|
78
82
|
return {}
|
|
79
83
|
return super().wiring_outputs
|
|
80
84
|
|
|
81
85
|
@property
|
|
82
86
|
def readable_outputs(self) -> Sequence[HandleMetadata]:
|
|
83
|
-
if self.is_inplace or self.
|
|
87
|
+
if self.is_inplace or self.classical_assignment:
|
|
84
88
|
return []
|
|
85
89
|
return [
|
|
86
90
|
HandleMetadata(
|
|
@@ -532,7 +532,7 @@ class QuantumNumeric(QuantumScalar):
|
|
|
532
532
|
|
|
533
533
|
|
|
534
534
|
class RegisterQuantumType(BaseModel):
|
|
535
|
-
quantum_types: "ConcreteQuantumType"
|
|
535
|
+
quantum_types: "ConcreteQuantumType" = Field(default_factory=QuantumBitvector)
|
|
536
536
|
size: int = Field(default=1)
|
|
537
537
|
|
|
538
538
|
@property
|
|
@@ -44,9 +44,6 @@ TASKS_VISUALIZE_SUFFIX = TASKS_SUFFIX + "/visualize"
|
|
|
44
44
|
TASKS_VISUAL_MODEL_SUFFIX = TASKS_SUFFIX + "/visual_model"
|
|
45
45
|
TASKS_SOLVE_SUFFIX = "/tasks/solve"
|
|
46
46
|
|
|
47
|
-
CHEMISTRY_QMOD_PATH = "/generate_model/chemistry/qmod"
|
|
48
|
-
|
|
49
|
-
|
|
50
47
|
TASK_TRAIN_SUFFIX = TASKS_SUFFIX + "/train"
|
|
51
48
|
TASK_TEST_SUFFIX = TASKS_SUFFIX + "/test"
|
|
52
49
|
TASK_PREDICT_SUFFIX = TASKS_SUFFIX + "/predict"
|
|
@@ -75,6 +72,8 @@ CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX = "/execution_input"
|
|
|
75
72
|
CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_FULL = (
|
|
76
73
|
CONVERSION_PREFIX + CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX
|
|
77
74
|
)
|
|
75
|
+
QASM_TO_QMOD_SUFFIX = "/qasm_to_qmod"
|
|
76
|
+
QASM_TO_QMOD_FULL_PATH = CONVERSION_PREFIX + QASM_TO_QMOD_SUFFIX
|
|
78
77
|
|
|
79
78
|
STATIC_SEMANTICS_VALIDATION_PATH = "/validate_static_semantics"
|
|
80
79
|
|