classiq 0.51.0__py3-none-any.whl → 0.52.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/_internals/api_wrapper.py +41 -15
- classiq/_internals/authentication/auth0.py +20 -4
- classiq/_internals/authentication/password_manager.py +16 -4
- classiq/_internals/client.py +2 -2
- classiq/_internals/host_checker.py +5 -3
- classiq/_internals/jobs.py +3 -3
- classiq/analyzer/analyzer_utilities.py +1 -1
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/applications/combinatorial_helpers/pyomo_utils.py +3 -1
- classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
- classiq/applications/qnn/qlayer.py +2 -2
- classiq/execution/__init__.py +3 -0
- classiq/execution/execution_session.py +2 -2
- classiq/execution/iqcc.py +63 -0
- classiq/execution/jobs.py +2 -2
- classiq/executor.py +2 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +19 -9
- classiq/interface/analyzer/cytoscape_graph.py +10 -3
- classiq/interface/analyzer/result.py +6 -5
- classiq/interface/applications/qsvm.py +13 -12
- classiq/interface/backend/backend_preferences.py +78 -105
- classiq/interface/backend/ionq/ionq_quantum_program.py +12 -19
- classiq/interface/backend/pydantic_backend.py +24 -12
- classiq/interface/backend/quantum_backend_providers.py +2 -0
- classiq/interface/chemistry/fermionic_operator.py +7 -7
- classiq/interface/chemistry/ground_state_problem.py +23 -18
- classiq/interface/chemistry/molecule.py +10 -5
- classiq/interface/chemistry/operator.py +71 -44
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +2 -1
- classiq/interface/debug_info/debug_info.py +3 -4
- classiq/interface/execution/iqcc.py +21 -0
- classiq/interface/execution/jobs.py +10 -10
- classiq/interface/executor/aws_execution_cost.py +37 -20
- classiq/interface/executor/execution_preferences.py +1 -2
- classiq/interface/executor/execution_request.py +2 -2
- classiq/interface/executor/execution_result.py +4 -2
- classiq/interface/executor/iqae_result.py +1 -1
- classiq/interface/executor/optimizer_preferences.py +14 -10
- classiq/interface/executor/quantum_code.py +21 -16
- classiq/interface/executor/register_initialization.py +10 -10
- classiq/interface/executor/result.py +19 -16
- classiq/interface/executor/vqe_result.py +1 -1
- classiq/interface/finance/function_input.py +27 -18
- classiq/interface/finance/log_normal_model_input.py +2 -2
- classiq/interface/finance/model_input.py +3 -2
- classiq/interface/generator/amplitude_loading.py +8 -6
- classiq/interface/generator/arith/argument_utils.py +24 -0
- classiq/interface/generator/arith/arithmetic.py +5 -3
- classiq/interface/generator/arith/arithmetic_expression_abc.py +36 -14
- classiq/interface/generator/arith/arithmetic_operations.py +6 -3
- classiq/interface/generator/arith/binary_ops.py +88 -63
- classiq/interface/generator/arith/extremum_operations.py +22 -13
- classiq/interface/generator/arith/logical_ops.py +6 -4
- classiq/interface/generator/arith/number_utils.py +3 -3
- classiq/interface/generator/arith/register_user_input.py +32 -17
- classiq/interface/generator/arith/unary_ops.py +5 -4
- classiq/interface/generator/chemistry_function_params.py +2 -1
- classiq/interface/generator/circuit_code/circuit_code.py +2 -1
- classiq/interface/generator/commuting_pauli_exponentiation.py +6 -5
- classiq/interface/generator/complex_type.py +14 -18
- classiq/interface/generator/control_state.py +32 -26
- classiq/interface/generator/expressions/expression.py +6 -5
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +3 -3
- classiq/interface/generator/function_params.py +22 -39
- classiq/interface/generator/functions/classical_function_declaration.py +1 -1
- classiq/interface/generator/functions/classical_type.py +32 -23
- classiq/interface/generator/functions/concrete_types.py +8 -7
- classiq/interface/generator/functions/function_declaration.py +4 -5
- classiq/interface/generator/functions/type_name.py +5 -4
- classiq/interface/generator/generated_circuit_data.py +9 -6
- classiq/interface/generator/grover_diffuser.py +26 -18
- classiq/interface/generator/grover_operator.py +32 -22
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +3 -4
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +8 -7
- classiq/interface/generator/hardware/hardware_data.py +27 -26
- classiq/interface/generator/hardware_efficient_ansatz.py +11 -6
- classiq/interface/generator/hartree_fock.py +2 -1
- classiq/interface/generator/identity.py +7 -2
- classiq/interface/generator/linear_pauli_rotations.py +27 -14
- classiq/interface/generator/mcu.py +15 -12
- classiq/interface/generator/mcx.py +18 -10
- classiq/interface/generator/model/constraints.py +4 -2
- classiq/interface/generator/model/model.py +2 -1
- classiq/interface/generator/model/preferences/preferences.py +30 -32
- classiq/interface/generator/oracles/custom_oracle.py +13 -10
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +37 -21
- classiq/interface/generator/qpe.py +38 -26
- classiq/interface/generator/qsvm.py +4 -4
- classiq/interface/generator/quantum_function_call.py +57 -44
- classiq/interface/generator/quantum_program.py +8 -6
- classiq/interface/generator/range_types.py +10 -11
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +9 -5
- classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
- classiq/interface/generator/standard_gates/u_gate.py +7 -10
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
- classiq/interface/generator/state_preparation/distributions.py +12 -12
- classiq/interface/generator/state_preparation/state_preparation.py +22 -16
- classiq/interface/generator/types/enum_declaration.py +2 -1
- classiq/interface/generator/ucc.py +2 -1
- classiq/interface/generator/unitary_gate.py +2 -1
- classiq/interface/generator/user_defined_function_params.py +3 -0
- classiq/interface/generator/visitor.py +1 -1
- classiq/interface/hardware.py +18 -3
- classiq/interface/helpers/custom_pydantic_types.py +38 -47
- classiq/interface/helpers/pydantic_model_helpers.py +3 -2
- classiq/interface/helpers/versioned_model.py +1 -4
- classiq/interface/ide/ide_data.py +5 -5
- classiq/interface/ide/visual_model.py +5 -5
- classiq/interface/interface_version.py +1 -1
- classiq/interface/jobs.py +12 -22
- classiq/interface/model/bind_operation.py +2 -1
- classiq/interface/model/classical_parameter_declaration.py +10 -4
- classiq/interface/model/handle_binding.py +20 -24
- classiq/interface/model/inplace_binary_operation.py +16 -9
- classiq/interface/model/model.py +21 -11
- classiq/interface/model/port_declaration.py +10 -7
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +6 -4
- classiq/interface/model/quantum_function_declaration.py +22 -11
- classiq/interface/model/quantum_statement.py +6 -7
- classiq/interface/model/quantum_type.py +22 -19
- classiq/interface/model/statement_block.py +9 -9
- classiq/interface/server/global_versions.py +4 -5
- classiq/interface/server/routes.py +8 -0
- classiq/model_expansions/evaluators/parameter_types.py +3 -3
- classiq/model_expansions/expression_renamer.py +1 -1
- classiq/model_expansions/quantum_operations/control.py +11 -12
- classiq/model_expansions/quantum_operations/emitter.py +22 -0
- classiq/model_expansions/quantum_operations/expression_operation.py +2 -20
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +65 -14
- classiq/model_expansions/quantum_operations/invert.py +1 -1
- classiq/model_expansions/quantum_operations/phase.py +4 -5
- classiq/model_expansions/quantum_operations/power.py +1 -1
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +50 -9
- classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
- classiq/model_expansions/quantum_operations/within_apply.py +1 -1
- classiq/qmod/builtins/__init__.py +1 -3
- classiq/qmod/builtins/functions/__init__.py +4 -0
- classiq/qmod/builtins/functions/arithmetic.py +10 -0
- classiq/qmod/create_model_function.py +14 -8
- classiq/qmod/quantum_expandable.py +22 -9
- classiq/qmod/quantum_function.py +1 -1
- classiq/qmod/semantics/static_semantics_visitor.py +3 -1
- classiq/qmod/type_attribute_remover.py +1 -1
- classiq/qmod/write_qmod.py +2 -4
- classiq/synthesis.py +11 -13
- {classiq-0.51.0.dist-info → classiq-0.52.0.dist-info}/METADATA +3 -2
- {classiq-0.51.0.dist-info → classiq-0.52.0.dist-info}/RECORD +150 -148
- {classiq-0.51.0.dist-info → classiq-0.52.0.dist-info}/WHEEL +0 -0
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
3
3
|
from typing import Any, Dict
|
4
4
|
|
5
5
|
import pydantic
|
6
|
-
from pydantic import BaseModel
|
6
|
+
from pydantic import BaseModel, ConfigDict
|
7
7
|
|
8
8
|
from classiq.interface.exceptions import ClassiqValueError
|
9
9
|
from classiq.interface.generator.arith.register_user_input import RegisterUserInput
|
@@ -18,45 +18,52 @@ class ControlState(BaseModel):
|
|
18
18
|
default=_DEFAULT_NUM_CONTROL_QUBITS, description="Number of control qubits"
|
19
19
|
)
|
20
20
|
ctrl_state: str = pydantic.Field(
|
21
|
-
default=_INVALID_CONTROL_STATE,
|
21
|
+
default=_INVALID_CONTROL_STATE,
|
22
|
+
description="Control state string",
|
23
|
+
validate_default=True,
|
24
|
+
)
|
25
|
+
name: str = pydantic.Field(
|
26
|
+
default=_DEFAULT_CONTROL_NAME, description="Control name"
|
22
27
|
)
|
23
|
-
name: str = pydantic.Field(default=None, description="Control name")
|
24
28
|
|
25
|
-
@pydantic.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
@pydantic.model_validator(mode="before")
|
30
|
+
@classmethod
|
31
|
+
def _validate_control(cls, values: Any) -> Dict[str, Any]:
|
32
|
+
if isinstance(values, dict):
|
33
|
+
num_ctrl_qubits: int = (
|
34
|
+
values.get("num_ctrl_qubits", _DEFAULT_NUM_CONTROL_QUBITS) or 0
|
35
|
+
)
|
31
36
|
|
32
|
-
|
33
|
-
ctrl_state = "1" * num_ctrl_qubits
|
34
|
-
values["ctrl_state"] = ctrl_state
|
37
|
+
ctrl_state: str = values.get("ctrl_state") or _INVALID_CONTROL_STATE
|
35
38
|
|
36
|
-
|
39
|
+
if ctrl_state == _INVALID_CONTROL_STATE:
|
40
|
+
ctrl_state = "1" * num_ctrl_qubits
|
41
|
+
values["ctrl_state"] = ctrl_state
|
37
42
|
|
38
|
-
|
39
|
-
num_ctrl_qubits = len(ctrl_state)
|
40
|
-
values["num_ctrl_qubits"] = num_ctrl_qubits
|
43
|
+
cls.validate_control_string(ctrl_state)
|
41
44
|
|
42
|
-
|
43
|
-
|
44
|
-
"
|
45
|
-
|
45
|
+
if num_ctrl_qubits == _DEFAULT_NUM_CONTROL_QUBITS:
|
46
|
+
num_ctrl_qubits = len(ctrl_state)
|
47
|
+
values["num_ctrl_qubits"] = num_ctrl_qubits
|
48
|
+
|
49
|
+
if len(ctrl_state) != num_ctrl_qubits:
|
50
|
+
raise ClassiqValueError(
|
51
|
+
"Control state length should be equal to the number of control qubits"
|
52
|
+
)
|
46
53
|
|
47
|
-
|
48
|
-
|
54
|
+
if "name" not in values or values["name"] is None:
|
55
|
+
values["name"] = f"{_DEFAULT_CONTROL_NAME}_{ctrl_state}"
|
49
56
|
|
50
57
|
return values
|
51
58
|
|
52
59
|
@staticmethod
|
53
60
|
def validate_control_string(ctrl_state: str) -> None:
|
61
|
+
if not ctrl_state:
|
62
|
+
raise ClassiqValueError("Control state cannot be empty")
|
54
63
|
if not set(ctrl_state) <= {"1", "0"}:
|
55
64
|
raise ClassiqValueError(
|
56
65
|
f"Control state can only be constructed from 0 and 1, received: {ctrl_state}"
|
57
66
|
)
|
58
|
-
if not ctrl_state:
|
59
|
-
raise ClassiqValueError("Control state cannot be empty")
|
60
67
|
|
61
68
|
def __str__(self) -> str:
|
62
69
|
return self.ctrl_state
|
@@ -71,5 +78,4 @@ class ControlState(BaseModel):
|
|
71
78
|
def rename(self, name: str) -> ControlState:
|
72
79
|
return ControlState(ctrl_state=self.ctrl_state, name=name)
|
73
80
|
|
74
|
-
|
75
|
-
frozen = True
|
81
|
+
model_config = ConfigDict(frozen=True)
|
@@ -3,7 +3,7 @@ import sys
|
|
3
3
|
from typing import Any, Mapping, Optional, Type
|
4
4
|
|
5
5
|
import pydantic
|
6
|
-
from pydantic import PrivateAttr
|
6
|
+
from pydantic import ConfigDict, PrivateAttr
|
7
7
|
|
8
8
|
from classiq.interface.ast_node import HashableASTNode
|
9
9
|
from classiq.interface.exceptions import ClassiqError
|
@@ -31,7 +31,8 @@ class Expression(HashableASTNode):
|
|
31
31
|
|
32
32
|
self._try_to_immediate_evaluate()
|
33
33
|
|
34
|
-
@pydantic.
|
34
|
+
@pydantic.field_validator("expr")
|
35
|
+
@classmethod
|
35
36
|
def validate_expression(cls, expr: str) -> str:
|
36
37
|
supported_functions = (
|
37
38
|
SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS_QMOD
|
@@ -41,7 +42,8 @@ class Expression(HashableASTNode):
|
|
41
42
|
validate_expression_str(expr, supported_functions=supported_functions)
|
42
43
|
return expr
|
43
44
|
|
44
|
-
@pydantic.
|
45
|
+
@pydantic.field_validator("expr")
|
46
|
+
@classmethod
|
45
47
|
def format_expression(cls, expr: str) -> str:
|
46
48
|
if sys.version_info >= (3, 9):
|
47
49
|
expr = ast.unparse(ast.parse(expr))
|
@@ -97,8 +99,7 @@ class Expression(HashableASTNode):
|
|
97
99
|
def is_constant(self) -> bool:
|
98
100
|
return self.value.is_constant()
|
99
101
|
|
100
|
-
|
101
|
-
frozen = True
|
102
|
+
model_config = ConfigDict(frozen=True)
|
102
103
|
|
103
104
|
def __str__(self) -> str:
|
104
105
|
return self.expr
|
@@ -29,10 +29,10 @@ class QmodQNumProxy(QmodQScalarProxy):
|
|
29
29
|
self, handle: HandleBinding, size: int, fraction_digits: int, is_signed: bool
|
30
30
|
) -> None:
|
31
31
|
super().__init__(handle, size)
|
32
|
-
if fraction_digits
|
32
|
+
if fraction_digits > size:
|
33
33
|
raise ClassiqValueError(
|
34
|
-
f"
|
35
|
-
f"
|
34
|
+
f"Quantum numeric of size {size} cannot have {fraction_digits} "
|
35
|
+
f"fraction digits"
|
36
36
|
)
|
37
37
|
self._fraction_digits = fraction_digits
|
38
38
|
self._is_signed = is_signed
|
@@ -17,7 +17,8 @@ from typing import (
|
|
17
17
|
|
18
18
|
import pydantic
|
19
19
|
import sympy
|
20
|
-
from pydantic
|
20
|
+
from pydantic import BeforeValidator, ConfigDict
|
21
|
+
from typing_extensions import Annotated
|
21
22
|
|
22
23
|
from classiq.interface.enum_utils import StrEnum
|
23
24
|
from classiq.interface.exceptions import ClassiqValueError
|
@@ -25,6 +26,7 @@ from classiq.interface.generator.arith.arithmetic_expression_validator import (
|
|
25
26
|
validate_expression,
|
26
27
|
)
|
27
28
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
29
|
+
from classiq.interface.generator.parameters import ParameterFloatType
|
28
30
|
from classiq.interface.helpers.custom_pydantic_types import PydanticNonEmptyString
|
29
31
|
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
30
32
|
HashablePydanticBaseModel,
|
@@ -126,6 +128,22 @@ def validate_expression_str(
|
|
126
128
|
)
|
127
129
|
|
128
130
|
|
131
|
+
def validate_parameters(value: Any) -> Any:
|
132
|
+
if isinstance(value, str):
|
133
|
+
validate_expression_str(value)
|
134
|
+
elif isinstance(value, sympy.Expr):
|
135
|
+
return str(value)
|
136
|
+
try:
|
137
|
+
return float(value)
|
138
|
+
except ValueError:
|
139
|
+
return value
|
140
|
+
|
141
|
+
|
142
|
+
FunctionParamsNumericParameter = Annotated[
|
143
|
+
ParameterFloatType, BeforeValidator(validate_parameters)
|
144
|
+
]
|
145
|
+
|
146
|
+
|
129
147
|
class PortDirection(StrEnum):
|
130
148
|
Input = "input"
|
131
149
|
Output = "output"
|
@@ -197,20 +215,6 @@ class FunctionParams(HashablePydanticBaseModel):
|
|
197
215
|
if self.discriminator() not in _UNVALIDATED_FUNCTIONS:
|
198
216
|
self._validate_total_io_sizes()
|
199
217
|
|
200
|
-
def is_field_param_type(self, name: str, param_type_signature: str) -> bool:
|
201
|
-
f = type(self).__fields__[name]
|
202
|
-
return isinstance(f, ModelField) and (
|
203
|
-
param_type_signature in f.field_info.extra
|
204
|
-
)
|
205
|
-
|
206
|
-
def is_field_gen_param(self, name: str) -> bool:
|
207
|
-
return self.is_field_param_type(
|
208
|
-
name, "is_gen_param"
|
209
|
-
) or self.is_field_exec_param(name)
|
210
|
-
|
211
|
-
def is_field_exec_param(self, name: str) -> bool:
|
212
|
-
return self.is_field_param_type(name, "is_exec_param")
|
213
|
-
|
214
218
|
def is_powerable(self, strict_zero_ios: bool = True) -> bool:
|
215
219
|
input_names = set(self.inputs_full(strict_zero_ios))
|
216
220
|
output_names = set(self._output_names)
|
@@ -261,28 +265,7 @@ class FunctionParams(HashablePydanticBaseModel):
|
|
261
265
|
def discriminator(cls) -> FunctionParamsDiscriminator:
|
262
266
|
return cls.__name__
|
263
267
|
|
264
|
-
|
265
|
-
def _params(self) -> List[str]:
|
266
|
-
return [
|
267
|
-
name
|
268
|
-
for name, field in self.__fields__.items()
|
269
|
-
if field.field_info.extra.get("is_exec_param", False)
|
270
|
-
]
|
271
|
-
|
272
|
-
@pydantic.validator("*", pre=True)
|
273
|
-
def validate_parameters(cls, value: Any, field: pydantic.fields.ModelField) -> Any:
|
274
|
-
if (
|
275
|
-
"is_exec_param" in field.field_info.extra
|
276
|
-
or "is_gen_param" in field.field_info.extra
|
277
|
-
):
|
278
|
-
if isinstance(value, str):
|
279
|
-
validate_expression_str(value)
|
280
|
-
elif isinstance(value, sympy.Expr):
|
281
|
-
return str(value)
|
282
|
-
return value
|
283
|
-
|
284
|
-
class Config:
|
285
|
-
frozen = True
|
268
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
286
269
|
|
287
270
|
|
288
271
|
def parse_function_params(
|
@@ -306,12 +289,12 @@ def parse_function_params(
|
|
306
289
|
if len(matching_classes) != 1:
|
307
290
|
if default_parser_class is not None:
|
308
291
|
try:
|
309
|
-
return default_parser_class.
|
292
|
+
return default_parser_class.model_validate(params)
|
310
293
|
except Exception:
|
311
294
|
raise bad_function_error from None
|
312
295
|
raise bad_function_error
|
313
296
|
|
314
|
-
return matching_classes[0].
|
297
|
+
return matching_classes[0].model_validate(params)
|
315
298
|
|
316
299
|
|
317
300
|
def parse_function_params_values(
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Union
|
2
2
|
|
3
3
|
import pydantic
|
4
|
-
from pydantic import
|
4
|
+
from pydantic import ConfigDict
|
5
5
|
from sympy import IndexedBase, Symbol
|
6
6
|
|
7
7
|
from classiq.interface.ast_node import HashableASTNode
|
@@ -22,8 +22,7 @@ class ClassicalType(HashableASTNode):
|
|
22
22
|
def as_symbolic(self, name: str) -> Union[NamedSymbol, List[NamedSymbol]]:
|
23
23
|
return Symbol(name)
|
24
24
|
|
25
|
-
|
26
|
-
extra = Extra.forbid
|
25
|
+
model_config = ConfigDict(extra="forbid")
|
27
26
|
|
28
27
|
def __str__(self) -> str:
|
29
28
|
return str(type(self).__name__)
|
@@ -35,8 +34,9 @@ class Integer(ClassicalType):
|
|
35
34
|
def as_symbolic(self, name: str) -> Symbol:
|
36
35
|
return Symbol(name, integer=True)
|
37
36
|
|
38
|
-
@pydantic.
|
39
|
-
|
37
|
+
@pydantic.model_validator(mode="before")
|
38
|
+
@classmethod
|
39
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
40
40
|
return values_with_discriminator(values, "kind", "int")
|
41
41
|
|
42
42
|
|
@@ -46,16 +46,18 @@ class Real(ClassicalType):
|
|
46
46
|
def as_symbolic(self, name: str) -> Symbol:
|
47
47
|
return Symbol(name, real=True)
|
48
48
|
|
49
|
-
@pydantic.
|
50
|
-
|
49
|
+
@pydantic.model_validator(mode="before")
|
50
|
+
@classmethod
|
51
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
51
52
|
return values_with_discriminator(values, "kind", "real")
|
52
53
|
|
53
54
|
|
54
55
|
class Bool(ClassicalType):
|
55
56
|
kind: Literal["bool"]
|
56
57
|
|
57
|
-
@pydantic.
|
58
|
-
|
58
|
+
@pydantic.model_validator(mode="before")
|
59
|
+
@classmethod
|
60
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
59
61
|
return values_with_discriminator(values, "kind", "bool")
|
60
62
|
|
61
63
|
|
@@ -66,16 +68,18 @@ class ClassicalList(ClassicalType):
|
|
66
68
|
def as_symbolic(self, name: str) -> Symbol:
|
67
69
|
return IndexedBase(name)
|
68
70
|
|
69
|
-
@pydantic.
|
70
|
-
|
71
|
+
@pydantic.model_validator(mode="before")
|
72
|
+
@classmethod
|
73
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
71
74
|
return values_with_discriminator(values, "kind", "list")
|
72
75
|
|
73
76
|
|
74
77
|
class StructMetaType(ClassicalType):
|
75
78
|
kind: Literal["type_proxy"]
|
76
79
|
|
77
|
-
@pydantic.
|
78
|
-
|
80
|
+
@pydantic.model_validator(mode="before")
|
81
|
+
@classmethod
|
82
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
79
83
|
return values_with_discriminator(values, "kind", "type_proxy")
|
80
84
|
|
81
85
|
|
@@ -87,8 +91,9 @@ class ClassicalArray(ClassicalType):
|
|
87
91
|
def as_symbolic(self, name: str) -> list:
|
88
92
|
return [self.element_type.as_symbolic(f"{name}_{i}") for i in range(self.size)]
|
89
93
|
|
90
|
-
@pydantic.
|
91
|
-
|
94
|
+
@pydantic.model_validator(mode="before")
|
95
|
+
@classmethod
|
96
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
92
97
|
return values_with_discriminator(values, "kind", "array")
|
93
98
|
|
94
99
|
|
@@ -99,32 +104,36 @@ class OpaqueHandle(ClassicalType):
|
|
99
104
|
class VQEResult(OpaqueHandle):
|
100
105
|
kind: Literal["vqe_result"]
|
101
106
|
|
102
|
-
@pydantic.
|
103
|
-
|
107
|
+
@pydantic.model_validator(mode="before")
|
108
|
+
@classmethod
|
109
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
104
110
|
return values_with_discriminator(values, "kind", "vqe_result")
|
105
111
|
|
106
112
|
|
107
113
|
class Histogram(OpaqueHandle):
|
108
114
|
kind: Literal["histogram"]
|
109
115
|
|
110
|
-
@pydantic.
|
111
|
-
|
116
|
+
@pydantic.model_validator(mode="before")
|
117
|
+
@classmethod
|
118
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
112
119
|
return values_with_discriminator(values, "kind", "histogram")
|
113
120
|
|
114
121
|
|
115
122
|
class Estimation(OpaqueHandle):
|
116
123
|
kind: Literal["estimation_result"]
|
117
124
|
|
118
|
-
@pydantic.
|
119
|
-
|
125
|
+
@pydantic.model_validator(mode="before")
|
126
|
+
@classmethod
|
127
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
120
128
|
return values_with_discriminator(values, "kind", "estimation_result")
|
121
129
|
|
122
130
|
|
123
131
|
class IQAERes(OpaqueHandle):
|
124
132
|
kind: Literal["iqae_result"]
|
125
133
|
|
126
|
-
@pydantic.
|
127
|
-
|
134
|
+
@pydantic.model_validator(mode="before")
|
135
|
+
@classmethod
|
136
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
128
137
|
return values_with_discriminator(values, "kind", "iqae_result")
|
129
138
|
|
130
139
|
|
@@ -40,16 +40,17 @@ ConcreteClassicalType = Annotated[
|
|
40
40
|
],
|
41
41
|
Field(discriminator="kind"),
|
42
42
|
]
|
43
|
-
ClassicalList.
|
44
|
-
ClassicalArray.
|
43
|
+
ClassicalList.model_rebuild()
|
44
|
+
ClassicalArray.model_rebuild()
|
45
45
|
|
46
|
-
|
46
|
+
NativePythonClassicalTypes = (int, float, bool, list)
|
47
|
+
PythonClassicalPydanticTypes = (Enum,)
|
47
48
|
|
48
49
|
ConcreteQuantumType = Annotated[
|
49
50
|
Union[QuantumBit, QuantumBitvector, QuantumNumeric, TypeName],
|
50
51
|
Field(discriminator="kind", default_factory=QuantumBitvector),
|
51
52
|
]
|
52
|
-
QuantumBitvector.
|
53
|
-
TypeName.
|
54
|
-
QStructDeclaration.
|
55
|
-
RegisterQuantumType.
|
53
|
+
QuantumBitvector.model_rebuild()
|
54
|
+
TypeName.model_rebuild()
|
55
|
+
QStructDeclaration.model_rebuild()
|
56
|
+
RegisterQuantumType.model_rebuild()
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import abc
|
2
2
|
from typing import Sequence
|
3
3
|
|
4
|
-
import
|
4
|
+
from pydantic import ConfigDict
|
5
5
|
|
6
6
|
from classiq.interface.model.classical_parameter_declaration import (
|
7
7
|
AnonClassicalParameterDeclaration,
|
@@ -16,11 +16,10 @@ class FunctionDeclaration(Parameter, abc.ABC):
|
|
16
16
|
|
17
17
|
@property
|
18
18
|
@abc.abstractmethod
|
19
|
-
def param_decls(self) -> Sequence[AnonClassicalParameterDeclaration]:
|
19
|
+
def param_decls(self) -> Sequence["AnonClassicalParameterDeclaration"]:
|
20
20
|
pass
|
21
21
|
|
22
|
-
|
23
|
-
extra = pydantic.Extra.forbid
|
22
|
+
model_config = ConfigDict(extra="forbid")
|
24
23
|
|
25
24
|
|
26
|
-
FunctionDeclaration.
|
25
|
+
FunctionDeclaration.model_rebuild()
|
@@ -16,15 +16,16 @@ if TYPE_CHECKING:
|
|
16
16
|
from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
|
17
17
|
|
18
18
|
|
19
|
-
class TypeName(ClassicalType, QuantumType):
|
19
|
+
class TypeName(ClassicalType, QuantumType):
|
20
20
|
kind: Literal["struct_instance"]
|
21
21
|
name: str = pydantic.Field(description="The type name of the instance")
|
22
22
|
_assigned_fields: Optional[Mapping[str, "ConcreteQuantumType"]] = (
|
23
23
|
pydantic.PrivateAttr(default=None)
|
24
24
|
)
|
25
25
|
|
26
|
-
@pydantic.
|
27
|
-
|
26
|
+
@pydantic.model_validator(mode="before")
|
27
|
+
@classmethod
|
28
|
+
def _set_kind(cls, values: Any) -> Dict[str, Any]:
|
28
29
|
return values_with_discriminator(values, "kind", "struct_instance")
|
29
30
|
|
30
31
|
def _update_size_in_bits_from_declaration(self) -> None:
|
@@ -60,7 +61,7 @@ class TypeName(ClassicalType, QuantumType): # type:ignore[misc]
|
|
60
61
|
if self._assigned_fields is None:
|
61
62
|
qstruct_fields = QMODULE.qstruct_decls[self.name].fields
|
62
63
|
self._assigned_fields = {
|
63
|
-
field_name: field_type.
|
64
|
+
field_name: field_type.model_copy()
|
64
65
|
for field_name, field_type in qstruct_fields.items()
|
65
66
|
}
|
66
67
|
|
@@ -2,6 +2,7 @@ import logging
|
|
2
2
|
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
|
3
3
|
|
4
4
|
import pydantic
|
5
|
+
from pydantic import ConfigDict
|
5
6
|
from typing_extensions import TypeAlias
|
6
7
|
|
7
8
|
from classiq.interface.generator.control_state import ControlState
|
@@ -56,8 +57,8 @@ class GeneratedFunction(pydantic.BaseModel):
|
|
56
57
|
name: str
|
57
58
|
control_states: List[ControlState]
|
58
59
|
registers: List[GeneratedRegister] = list()
|
59
|
-
depth: Optional[int]
|
60
|
-
width: Optional[int]
|
60
|
+
depth: Optional[int] = pydantic.Field(default=None)
|
61
|
+
width: Optional[int] = pydantic.Field(default=None)
|
61
62
|
released_auxiliary_qubits: List[int] = list()
|
62
63
|
dangling_inputs: Dict[str, GeneratedRegister] = dict()
|
63
64
|
dangling_outputs: Dict[str, GeneratedRegister] = dict()
|
@@ -97,16 +98,18 @@ class GeneratedCircuitData(pydantic.BaseModel):
|
|
97
98
|
|
98
99
|
|
99
100
|
class FunctionDebugInfoInterface(pydantic.BaseModel):
|
100
|
-
generated_function: Optional[GeneratedFunction]
|
101
|
+
generated_function: Optional[GeneratedFunction] = pydantic.Field(default=None)
|
101
102
|
children: List["FunctionDebugInfoInterface"]
|
102
103
|
relative_qubits: Tuple[int, ...]
|
103
|
-
absolute_qubits: Optional[Tuple[int, ...]]
|
104
|
-
is_basis_gate: Optional[bool]
|
104
|
+
absolute_qubits: Optional[Tuple[int, ...]] = pydantic.Field(default=None)
|
105
|
+
is_basis_gate: Optional[bool] = pydantic.Field(default=None)
|
105
106
|
is_inverse: bool = pydantic.Field(default=False)
|
106
107
|
is_allocate_or_free: bool = pydantic.Field(default=False)
|
107
108
|
level: OperationLevel = pydantic.Field(default=OperationLevel.UNKNOWN)
|
108
109
|
parameters: List[OperationParameter] = list()
|
109
|
-
port_to_passed_variable_map: Dict[str, str] = pydantic.Field(
|
110
|
+
port_to_passed_variable_map: Dict[str, str] = pydantic.Field(default={})
|
111
|
+
|
112
|
+
model_config = ConfigDict(extra="allow")
|
110
113
|
# Temporary field to store the override debug info for parallel old/new visualization
|
111
114
|
override_debug_info: Optional["FunctionDebugInfoInterface"] = None
|
112
115
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Any, Dict, List, Set, Tuple, Union
|
2
2
|
|
3
3
|
import pydantic
|
4
|
+
from pydantic_core.core_schema import ValidationInfo
|
4
5
|
|
5
6
|
from classiq.interface.exceptions import ClassiqValueError
|
6
7
|
from classiq.interface.generator.arith.register_user_input import RegisterUserInput
|
@@ -29,28 +30,34 @@ class GroverDiffuser(FunctionParams):
|
|
29
30
|
self._inputs = {reg.name: reg for reg in self.variables}
|
30
31
|
self._outputs = {reg.name: reg for reg in self.variables}
|
31
32
|
|
32
|
-
@pydantic.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
@pydantic.model_validator(mode="before")
|
34
|
+
@classmethod
|
35
|
+
def _validate_state_preparation_name(cls, values: Any) -> Dict[str, Any]:
|
36
|
+
if (
|
37
|
+
isinstance(values, dict)
|
38
|
+
and isinstance(values.get("state_preparation_params"), CustomFunction)
|
39
|
+
and not values.get("state_preparation")
|
40
|
+
):
|
37
41
|
raise ClassiqValueError(
|
38
42
|
"Must receive the function name from the `state_preparation` field for user defined functions"
|
39
43
|
)
|
40
44
|
return values
|
41
45
|
|
42
|
-
@pydantic.
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
@pydantic.model_validator(mode="before")
|
47
|
+
@classmethod
|
48
|
+
def _parse_state_preparation(cls, values: Any) -> Dict[str, Any]:
|
49
|
+
if isinstance(values, dict):
|
50
|
+
parse_function_params_values(
|
51
|
+
values=values,
|
52
|
+
params_key="state_preparation_params",
|
53
|
+
discriminator_key="state_preparation",
|
54
|
+
param_classes={StatePreparation, CustomFunction},
|
55
|
+
default_parser_class=CustomFunction,
|
56
|
+
)
|
51
57
|
return values
|
52
58
|
|
53
|
-
@pydantic.
|
59
|
+
@pydantic.field_validator("variables")
|
60
|
+
@classmethod
|
54
61
|
def _validate_variables(
|
55
62
|
cls, variables: List[RegisterUserInput]
|
56
63
|
) -> List[RegisterUserInput]:
|
@@ -58,11 +65,12 @@ class GroverDiffuser(FunctionParams):
|
|
58
65
|
assert len(variables) == len(names), "Repeating names not allowed"
|
59
66
|
return variables
|
60
67
|
|
61
|
-
@pydantic.
|
68
|
+
@pydantic.field_validator("state_preparation_params")
|
69
|
+
@classmethod
|
62
70
|
def _validate_state_preparation(
|
63
|
-
cls, state_preparation_params: GroverStatePreparation,
|
71
|
+
cls, state_preparation_params: GroverStatePreparation, info: ValidationInfo
|
64
72
|
) -> GroverStatePreparation:
|
65
|
-
variables =
|
73
|
+
variables = info.data.get("variables", list())
|
66
74
|
sp_inputs = state_preparation_params.inputs_full(strict_zero_ios=False)
|
67
75
|
sp_outputs = state_preparation_params.outputs
|
68
76
|
if len(sp_inputs) == 1 and len(sp_outputs) == 1:
|