classiq 0.51.1__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/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 +38 -9
- 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 +4 -4
- 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.1.dist-info → classiq-0.52.0.dist-info}/METADATA +3 -2
- {classiq-0.51.1.dist-info → classiq-0.52.0.dist-info}/RECORD +149 -147
- {classiq-0.51.1.dist-info → classiq-0.52.0.dist-info}/WHEEL +0 -0
@@ -23,9 +23,7 @@ class ExponentiationConstraints(pydantic.BaseModel):
|
|
23
23
|
default=None,
|
24
24
|
description="Maximum approximation error of the exponentiation circuit.",
|
25
25
|
)
|
26
|
-
|
27
|
-
class Config:
|
28
|
-
frozen = True
|
26
|
+
model_config = pydantic.ConfigDict(frozen=True)
|
29
27
|
|
30
28
|
|
31
29
|
class Exponentiation(HamiltonianEvolution):
|
@@ -45,6 +43,7 @@ class Exponentiation(HamiltonianEvolution):
|
|
45
43
|
description="What attribute to optimize.",
|
46
44
|
)
|
47
45
|
|
48
|
-
@pydantic.
|
46
|
+
@pydantic.field_validator("pauli_operator")
|
47
|
+
@classmethod
|
49
48
|
def _validate_is_hermitian(cls, pauli_operator: PauliOperator) -> PauliOperator:
|
50
49
|
return operator.validate_operator_is_hermitian(pauli_operator)
|
@@ -2,10 +2,10 @@ import pydantic
|
|
2
2
|
|
3
3
|
from classiq.interface.chemistry import operator
|
4
4
|
from classiq.interface.chemistry.operator import PauliOperator
|
5
|
+
from classiq.interface.generator.function_params import FunctionParamsNumericParameter
|
5
6
|
from classiq.interface.generator.hamiltonian_evolution.hamiltonian_evolution import (
|
6
7
|
HamiltonianEvolution,
|
7
8
|
)
|
8
|
-
from classiq.interface.generator.parameters import ParameterFloatType
|
9
9
|
|
10
10
|
|
11
11
|
class QDrift(HamiltonianEvolution):
|
@@ -13,15 +13,15 @@ class QDrift(HamiltonianEvolution):
|
|
13
13
|
qDrift trotterization of a Hermitian operator; see https://arxiv.org/abs/1811.08017
|
14
14
|
"""
|
15
15
|
|
16
|
-
evolution_coefficient:
|
16
|
+
evolution_coefficient: FunctionParamsNumericParameter = pydantic.Field(
|
17
17
|
default=1.0,
|
18
18
|
description="A global coefficient multiplying the operator.",
|
19
|
-
is_exec_param=True,
|
20
19
|
)
|
21
20
|
num_qdrift: pydantic.PositiveInt = pydantic.Field(
|
22
21
|
description="The number of elements in the qDrift product.",
|
23
22
|
)
|
24
23
|
|
25
|
-
@pydantic.
|
24
|
+
@pydantic.field_validator("pauli_operator")
|
25
|
+
@classmethod
|
26
26
|
def _validate_is_hermitian(cls, pauli_operator: PauliOperator) -> PauliOperator:
|
27
27
|
return operator.validate_operator_is_hermitian(pauli_operator)
|
@@ -1,12 +1,13 @@
|
|
1
1
|
import pydantic
|
2
|
+
from pydantic import ConfigDict
|
2
3
|
|
3
4
|
from classiq.interface.chemistry import operator
|
4
5
|
from classiq.interface.chemistry.operator import PauliOperator
|
5
6
|
from classiq.interface.exceptions import ClassiqValueError
|
7
|
+
from classiq.interface.generator.function_params import FunctionParamsNumericParameter
|
6
8
|
from classiq.interface.generator.hamiltonian_evolution.hamiltonian_evolution import (
|
7
9
|
HamiltonianEvolution,
|
8
10
|
)
|
9
|
-
from classiq.interface.generator.parameters import ParameterFloatType
|
10
11
|
|
11
12
|
|
12
13
|
class SuzukiParameters(pydantic.BaseModel):
|
@@ -18,7 +19,8 @@ class SuzukiParameters(pydantic.BaseModel):
|
|
18
19
|
default=1, description="The number of repetitions in the Suzuki-Trotter"
|
19
20
|
)
|
20
21
|
|
21
|
-
@pydantic.
|
22
|
+
@pydantic.field_validator("order")
|
23
|
+
@classmethod
|
22
24
|
def _validate_order(cls, order: int) -> int:
|
23
25
|
if order != 1 and order % 2:
|
24
26
|
raise ClassiqValueError(
|
@@ -26,8 +28,7 @@ class SuzukiParameters(pydantic.BaseModel):
|
|
26
28
|
)
|
27
29
|
return order
|
28
30
|
|
29
|
-
|
30
|
-
frozen = True
|
31
|
+
model_config = ConfigDict(frozen=True)
|
31
32
|
|
32
33
|
|
33
34
|
class SuzukiTrotter(HamiltonianEvolution):
|
@@ -35,10 +36,9 @@ class SuzukiTrotter(HamiltonianEvolution):
|
|
35
36
|
Suzuki trotterization of a Hermitian operator
|
36
37
|
"""
|
37
38
|
|
38
|
-
evolution_coefficient:
|
39
|
+
evolution_coefficient: FunctionParamsNumericParameter = pydantic.Field(
|
39
40
|
default=1.0,
|
40
41
|
description="A global coefficient multiplying the operator.",
|
41
|
-
is_exec_param=True,
|
42
42
|
)
|
43
43
|
suzuki_parameters: SuzukiParameters = pydantic.Field(
|
44
44
|
default_factory=SuzukiParameters, description="The Suziki parameters."
|
@@ -47,7 +47,8 @@ class SuzukiTrotter(HamiltonianEvolution):
|
|
47
47
|
default=False, description="Whether to disable the reordering of Pauli terms."
|
48
48
|
)
|
49
49
|
|
50
|
-
@pydantic.
|
50
|
+
@pydantic.field_validator("pauli_operator")
|
51
|
+
@classmethod
|
51
52
|
def _validate_no_complex_coefficients(
|
52
53
|
cls, pauli_operator: PauliOperator
|
53
54
|
) -> PauliOperator:
|
@@ -3,6 +3,7 @@ from collections import defaultdict
|
|
3
3
|
from typing import Any, Dict, List, MutableSet, Optional
|
4
4
|
|
5
5
|
import pydantic
|
6
|
+
from typing_extensions import Self
|
6
7
|
|
7
8
|
from classiq.interface.backend.backend_preferences import BackendPreferences
|
8
9
|
from classiq.interface.exceptions import ClassiqValueError
|
@@ -60,7 +61,8 @@ class HardwareData(pydantic.BaseModel):
|
|
60
61
|
"If false, the first / second qubit denotes the control / target, respectively",
|
61
62
|
)
|
62
63
|
|
63
|
-
@pydantic.
|
64
|
+
@pydantic.field_validator("connectivity_map")
|
65
|
+
@classmethod
|
64
66
|
def _validate_connectivity_map(
|
65
67
|
cls, connectivity_map: Optional[ConnectivityMap]
|
66
68
|
) -> Optional[ConnectivityMap]:
|
@@ -71,39 +73,37 @@ class HardwareData(pydantic.BaseModel):
|
|
71
73
|
connectivity_map = _reindex_qubits(connectivity_map)
|
72
74
|
return connectivity_map
|
73
75
|
|
74
|
-
@pydantic.
|
75
|
-
def _symmetrize_connectivity_map(
|
76
|
-
connectivity_map =
|
76
|
+
@pydantic.model_validator(mode="after")
|
77
|
+
def _symmetrize_connectivity_map(self) -> Self:
|
78
|
+
connectivity_map = self.connectivity_map
|
77
79
|
if connectivity_map is None:
|
78
|
-
return
|
80
|
+
return self
|
79
81
|
|
80
|
-
is_symmetric =
|
82
|
+
is_symmetric = self.is_symmetric_connectivity
|
81
83
|
if is_symmetric:
|
82
84
|
connectivity_map = _symmetrize_connectivity_map(connectivity_map)
|
83
|
-
|
85
|
+
self.connectivity_map = connectivity_map
|
84
86
|
|
85
87
|
if not _is_connected_map(connectivity_map):
|
86
88
|
raise ClassiqValueError(
|
87
89
|
f"Connectivity map must be connected: {connectivity_map} is not connected."
|
88
90
|
)
|
89
|
-
return
|
91
|
+
return self
|
90
92
|
|
91
|
-
@pydantic.
|
92
|
-
def _validate_basis_gates(
|
93
|
-
connectivity_map =
|
94
|
-
specified_basis_gates =
|
93
|
+
@pydantic.model_validator(mode="after")
|
94
|
+
def _validate_basis_gates(self) -> Self:
|
95
|
+
connectivity_map = self.connectivity_map
|
96
|
+
specified_basis_gates = self.basis_gates
|
95
97
|
if connectivity_map is None:
|
96
|
-
|
97
|
-
return
|
98
|
+
self.basis_gates = specified_basis_gates or list(DEFAULT_BASIS_GATES)
|
99
|
+
return self
|
98
100
|
|
99
|
-
is_symmetric_connectivity =
|
101
|
+
is_symmetric_connectivity = self.is_symmetric_connectivity
|
100
102
|
if is_symmetric_connectivity or _check_symmetry(connectivity_map):
|
101
|
-
|
102
|
-
return
|
103
|
+
self.basis_gates = specified_basis_gates or list(DEFAULT_BASIS_GATES)
|
104
|
+
return self
|
103
105
|
|
104
|
-
|
105
|
-
DEFAULT_ROUTING_BASIS_GATES
|
106
|
-
)
|
106
|
+
self.basis_gates = specified_basis_gates or list(DEFAULT_ROUTING_BASIS_GATES)
|
107
107
|
invalid_gates = [
|
108
108
|
gate
|
109
109
|
for gate in specified_basis_gates
|
@@ -115,7 +115,7 @@ class HardwareData(pydantic.BaseModel):
|
|
115
115
|
"is currently supported for the following two-qubit gates only: cx, ecr, rzx."
|
116
116
|
)
|
117
117
|
|
118
|
-
return
|
118
|
+
return self
|
119
119
|
|
120
120
|
|
121
121
|
class CustomHardwareSettings(HardwareData):
|
@@ -127,7 +127,8 @@ class CustomHardwareSettings(HardwareData):
|
|
127
127
|
|
128
128
|
_width: Optional[int] = pydantic.PrivateAttr(default=None)
|
129
129
|
|
130
|
-
@pydantic.
|
130
|
+
@pydantic.field_validator("basis_gates", mode="after")
|
131
|
+
@classmethod
|
131
132
|
def validate_basis_gates(cls, basis_gates: List[str]) -> List[TranspilerBasisGates]:
|
132
133
|
valid_gates = list(TranspilerBasisGates)
|
133
134
|
invalid_gates = [gate for gate in basis_gates if gate not in valid_gates]
|
@@ -179,7 +180,7 @@ def _node_dfs(
|
|
179
180
|
|
180
181
|
def _reindex_qubits(connectivity_map: ConnectivityMap) -> ConnectivityMap:
|
181
182
|
qubits = sorted({q for pair in connectivity_map for q in pair})
|
182
|
-
return [
|
183
|
+
return [[qubits.index(pair[0]), qubits.index(pair[1])] for pair in connectivity_map]
|
183
184
|
|
184
185
|
|
185
186
|
def _check_symmetry(connectivity_map: ConnectivityMap) -> bool:
|
@@ -191,14 +192,14 @@ def _symmetrize_connectivity_map(connectivity_map: ConnectivityMap) -> Connectiv
|
|
191
192
|
# A more complicated implementation than using set to maintain the order
|
192
193
|
connectivity_map_no_duplicates = []
|
193
194
|
for edge in connectivity_map:
|
194
|
-
reversed_edge =
|
195
|
+
reversed_edge = [edge[1], edge[0]]
|
195
196
|
if (
|
196
197
|
edge not in connectivity_map_no_duplicates
|
197
198
|
and reversed_edge not in connectivity_map_no_duplicates
|
198
199
|
):
|
199
200
|
connectivity_map_no_duplicates.append(edge)
|
200
201
|
reversed_connectivity_map = [
|
201
|
-
|
202
|
+
[edge[1], edge[0]] for edge in connectivity_map_no_duplicates
|
202
203
|
]
|
203
204
|
return connectivity_map_no_duplicates + reversed_connectivity_map
|
204
205
|
|
@@ -217,4 +218,4 @@ class SynthesisHardwareData(HardwareData):
|
|
217
218
|
Defaults to `None`.
|
218
219
|
"""
|
219
220
|
|
220
|
-
backend_data: Optional[BackendPreferences]
|
221
|
+
backend_data: Optional[BackendPreferences] = pydantic.Field(default=None)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import itertools
|
2
|
-
from typing import TYPE_CHECKING,
|
2
|
+
from typing import TYPE_CHECKING, List, Optional, Union
|
3
3
|
|
4
4
|
import pydantic
|
5
|
+
from pydantic_core.core_schema import ValidationInfo
|
5
6
|
|
6
7
|
from classiq.interface.enum_utils import StrEnum
|
7
8
|
from classiq.interface.exceptions import ClassiqValueError
|
@@ -44,6 +45,7 @@ class HardwareEfficientAnsatz(function_params.FunctionParams):
|
|
44
45
|
num_qubits: pydantic.PositiveInt = pydantic.Field(
|
45
46
|
default=None,
|
46
47
|
description="Number of qubits in the ansatz.",
|
48
|
+
validate_default=True,
|
47
49
|
)
|
48
50
|
reps: pydantic.PositiveInt = pydantic.Field(
|
49
51
|
default=1, description="Number of layers in the Ansatz"
|
@@ -62,11 +64,12 @@ class HardwareEfficientAnsatz(function_params.FunctionParams):
|
|
62
64
|
description="Prefix for the generated parameters",
|
63
65
|
)
|
64
66
|
|
65
|
-
@pydantic.
|
67
|
+
@pydantic.field_validator("num_qubits", mode="before")
|
68
|
+
@classmethod
|
66
69
|
def validate_num_qubits(
|
67
|
-
cls, num_qubits: Optional[pydantic.PositiveInt],
|
70
|
+
cls, num_qubits: Optional[pydantic.PositiveInt], info: ValidationInfo
|
68
71
|
) -> pydantic.PositiveInt:
|
69
|
-
connectivity_map =
|
72
|
+
connectivity_map = info.data.get("connectivity_map")
|
70
73
|
conn_map_is_not_list = (
|
71
74
|
isinstance(connectivity_map, SupportedConnectivityMaps)
|
72
75
|
or connectivity_map is None
|
@@ -101,7 +104,8 @@ class HardwareEfficientAnsatz(function_params.FunctionParams):
|
|
101
104
|
)
|
102
105
|
return num_qubits
|
103
106
|
|
104
|
-
@pydantic.
|
107
|
+
@pydantic.field_validator("one_qubit_gates")
|
108
|
+
@classmethod
|
105
109
|
def validate_one_qubit_gates(
|
106
110
|
cls, one_qubit_gates: Union[str, List[str]]
|
107
111
|
) -> Union[str, List[str]]:
|
@@ -113,7 +117,8 @@ class HardwareEfficientAnsatz(function_params.FunctionParams):
|
|
113
117
|
raise ClassiqValueError(f"Invalid one qubit gate: {one_qubit_gate}")
|
114
118
|
return one_qubit_gates
|
115
119
|
|
116
|
-
@pydantic.
|
120
|
+
@pydantic.field_validator("two_qubit_gates")
|
121
|
+
@classmethod
|
117
122
|
def validate_two_qubit_gates(
|
118
123
|
cls, two_qubit_gates: Union[str, List[str]]
|
119
124
|
) -> Union[str, List[str]]:
|
@@ -14,7 +14,8 @@ from classiq.interface.generator.chemistry_function_params import (
|
|
14
14
|
|
15
15
|
|
16
16
|
class HartreeFock(ChemistryFunctionParams):
|
17
|
-
@pydantic.
|
17
|
+
@pydantic.field_validator("gs_problem")
|
18
|
+
@classmethod
|
18
19
|
def validate_gs_problem(
|
19
20
|
cls, gs_problem: Any
|
20
21
|
) -> Union[MoleculeProblem, HamiltonianProblem]:
|
@@ -1,6 +1,8 @@
|
|
1
1
|
from typing import TYPE_CHECKING, List
|
2
2
|
|
3
3
|
import pydantic
|
4
|
+
from pydantic import Field
|
5
|
+
from typing_extensions import Annotated
|
4
6
|
|
5
7
|
from classiq.interface.generator.arith.register_user_input import RegisterUserInput
|
6
8
|
from classiq.interface.generator.function_params import FunctionParams
|
@@ -8,7 +10,9 @@ from classiq.interface.generator.function_params import FunctionParams
|
|
8
10
|
if TYPE_CHECKING:
|
9
11
|
NonEmptyRegisterUserInputList = List[RegisterUserInput]
|
10
12
|
else:
|
11
|
-
NonEmptyRegisterUserInputList =
|
13
|
+
NonEmptyRegisterUserInputList = Annotated[
|
14
|
+
List[RegisterUserInput], Field(min_length=1)
|
15
|
+
]
|
12
16
|
|
13
17
|
|
14
18
|
class Identity(FunctionParams):
|
@@ -16,7 +20,8 @@ class Identity(FunctionParams):
|
|
16
20
|
description="registers describing the state (ordered)"
|
17
21
|
)
|
18
22
|
|
19
|
-
@pydantic.
|
23
|
+
@pydantic.field_validator("arguments")
|
24
|
+
@classmethod
|
20
25
|
def _validate_argument_names(
|
21
26
|
cls, arguments: List[RegisterUserInput]
|
22
27
|
) -> List[RegisterUserInput]:
|
@@ -1,6 +1,8 @@
|
|
1
|
-
from typing import TYPE_CHECKING, Any,
|
1
|
+
from typing import TYPE_CHECKING, Any, List
|
2
2
|
|
3
3
|
import pydantic
|
4
|
+
from pydantic import StringConstraints
|
5
|
+
from typing_extensions import Annotated, Self
|
4
6
|
|
5
7
|
from classiq.interface.exceptions import ClassiqValueError
|
6
8
|
from classiq.interface.generator import function_params
|
@@ -9,15 +11,18 @@ from classiq.interface.generator.arith.register_user_input import RegisterArithm
|
|
9
11
|
STATE = "state"
|
10
12
|
TARGET = "target"
|
11
13
|
|
12
|
-
LENGTH_ERROR_MESSAGE = "
|
14
|
+
LENGTH_ERROR_MESSAGE = "Field required"
|
13
15
|
|
14
16
|
if TYPE_CHECKING:
|
15
17
|
PydanticPauliBasisStr = str
|
16
18
|
else:
|
17
|
-
PydanticPauliBasisStr =
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
PydanticPauliBasisStr = Annotated[
|
20
|
+
str,
|
21
|
+
StringConstraints(
|
22
|
+
to_lower=True,
|
23
|
+
pattern=r"[xyz]",
|
24
|
+
),
|
25
|
+
]
|
21
26
|
|
22
27
|
|
23
28
|
class LinearPauliRotations(function_params.FunctionParams):
|
@@ -56,19 +61,27 @@ class LinearPauliRotations(function_params.FunctionParams):
|
|
56
61
|
description="The offsets of the controlled rotations."
|
57
62
|
)
|
58
63
|
|
59
|
-
@pydantic.
|
64
|
+
@pydantic.field_validator("bases", "slopes", "offsets", mode="before")
|
65
|
+
@classmethod
|
60
66
|
def as_list(cls, v: Any) -> List[Any]:
|
61
67
|
if not isinstance(v, list):
|
62
68
|
v = [v]
|
63
|
-
|
69
|
+
res = []
|
70
|
+
for x in v:
|
71
|
+
element = x
|
72
|
+
if isinstance(x, str):
|
73
|
+
res.append(element.lower())
|
74
|
+
else:
|
75
|
+
res.append(element)
|
76
|
+
return res
|
64
77
|
|
65
|
-
@pydantic.
|
66
|
-
def validate_lists(
|
67
|
-
offsets =
|
68
|
-
bases =
|
69
|
-
slopes =
|
78
|
+
@pydantic.model_validator(mode="after")
|
79
|
+
def validate_lists(self) -> Self:
|
80
|
+
offsets = self.offsets or list()
|
81
|
+
bases = self.bases or list()
|
82
|
+
slopes = self.slopes or list()
|
70
83
|
if len(slopes) == len(offsets) and len(offsets) == len(bases):
|
71
|
-
return
|
84
|
+
return self
|
72
85
|
raise ClassiqValueError(LENGTH_ERROR_MESSAGE)
|
73
86
|
|
74
87
|
def _create_ios(self) -> None:
|
@@ -5,8 +5,10 @@ import pydantic
|
|
5
5
|
from classiq.interface.exceptions import ClassiqValueError
|
6
6
|
from classiq.interface.generator.arith.register_user_input import RegisterUserInput
|
7
7
|
from classiq.interface.generator.control_state import ControlState
|
8
|
-
from classiq.interface.generator.function_params import
|
9
|
-
|
8
|
+
from classiq.interface.generator.function_params import (
|
9
|
+
FunctionParams,
|
10
|
+
FunctionParamsNumericParameter,
|
11
|
+
)
|
10
12
|
|
11
13
|
CTRL = "CTRL"
|
12
14
|
TARGET = "TARGET"
|
@@ -29,17 +31,17 @@ class Mcu(FunctionParams):
|
|
29
31
|
e^(i*phi)*sin(theta/2) & e^(i*(phi+lam))*cos(theta/2) \\
|
30
32
|
"""
|
31
33
|
|
32
|
-
theta:
|
33
|
-
default=0, description="Theta radian angle."
|
34
|
+
theta: FunctionParamsNumericParameter = pydantic.Field(
|
35
|
+
default=0, description="Theta radian angle."
|
34
36
|
)
|
35
|
-
phi:
|
36
|
-
default=0, description="Phi radian angle."
|
37
|
+
phi: FunctionParamsNumericParameter = pydantic.Field(
|
38
|
+
default=0, description="Phi radian angle."
|
37
39
|
)
|
38
|
-
lam:
|
39
|
-
default=0, description="Lambda radian angle."
|
40
|
+
lam: FunctionParamsNumericParameter = pydantic.Field(
|
41
|
+
default=0, description="Lambda radian angle."
|
40
42
|
)
|
41
|
-
gam:
|
42
|
-
default=0, description="gam radian angle."
|
43
|
+
gam: FunctionParamsNumericParameter = pydantic.Field(
|
44
|
+
default=0, description="gam radian angle."
|
43
45
|
)
|
44
46
|
|
45
47
|
num_ctrl_qubits: Optional[pydantic.PositiveInt] = pydantic.Field(
|
@@ -49,8 +51,9 @@ class Mcu(FunctionParams):
|
|
49
51
|
default=None, description="string of the control state"
|
50
52
|
)
|
51
53
|
|
52
|
-
@pydantic.
|
53
|
-
|
54
|
+
@pydantic.model_validator(mode="before")
|
55
|
+
@classmethod
|
56
|
+
def _validate_control(cls, values: Any) -> Dict[str, Any]:
|
54
57
|
num_ctrl_qubits = values.get("num_ctrl_qubits")
|
55
58
|
ctrl_state = values.get("ctrl_state")
|
56
59
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Any, Dict, List, Optional
|
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
|
@@ -20,11 +21,15 @@ class Mcx(FunctionParams):
|
|
20
21
|
default_factory=list, description="registers describing the state (ordered)"
|
21
22
|
)
|
22
23
|
num_ctrl_qubits: Optional[pydantic.PositiveInt] = pydantic.Field(
|
23
|
-
description="number of control qubits"
|
24
|
+
description="number of control qubits",
|
25
|
+
default=None,
|
26
|
+
)
|
27
|
+
ctrl_state: str = pydantic.Field(
|
28
|
+
default="", description="control state string", validate_default=True
|
24
29
|
)
|
25
|
-
ctrl_state: str = pydantic.Field(default="", description="control state string")
|
26
30
|
|
27
|
-
@pydantic.
|
31
|
+
@pydantic.field_validator("arguments")
|
32
|
+
@classmethod
|
28
33
|
def _validate_argument_names(
|
29
34
|
cls, arguments: List[RegisterUserInput]
|
30
35
|
) -> List[RegisterUserInput]:
|
@@ -35,10 +40,11 @@ class Mcx(FunctionParams):
|
|
35
40
|
raise ClassiqValueError("Registers must have distinct names")
|
36
41
|
return arguments
|
37
42
|
|
38
|
-
@pydantic.
|
39
|
-
|
43
|
+
@pydantic.model_validator(mode="before")
|
44
|
+
@classmethod
|
45
|
+
def _validate_sizes(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
40
46
|
arguments_size = sum(arg.size for arg in values.get("arguments", list()))
|
41
|
-
|
47
|
+
num_ctrl_qubits = values.get("num_ctrl_qubits")
|
42
48
|
if not num_ctrl_qubits:
|
43
49
|
num_ctrl_qubits = arguments_size - 1
|
44
50
|
|
@@ -51,11 +57,13 @@ class Mcx(FunctionParams):
|
|
51
57
|
values["arguments"] = [ctrl_register, target_register]
|
52
58
|
elif num_ctrl_qubits != arguments_size - 1:
|
53
59
|
raise ClassiqValueError("Given sizes do not match")
|
54
|
-
|
60
|
+
values["num_ctrl_qubits"] = num_ctrl_qubits
|
61
|
+
return values
|
55
62
|
|
56
|
-
@pydantic.
|
57
|
-
|
58
|
-
|
63
|
+
@pydantic.field_validator("ctrl_state")
|
64
|
+
@classmethod
|
65
|
+
def _validate_ctrl_state(cls, ctrl_state: str, info: ValidationInfo) -> str:
|
66
|
+
num_ctrl_qubits = info.data.get("num_ctrl_qubits", -1)
|
59
67
|
if not ctrl_state:
|
60
68
|
return "1" * num_ctrl_qubits
|
61
69
|
if len(ctrl_state) != num_ctrl_qubits:
|
@@ -2,7 +2,7 @@ from collections import defaultdict
|
|
2
2
|
from typing import Dict, Optional, Union
|
3
3
|
|
4
4
|
import pydantic
|
5
|
-
from pydantic import BaseModel,
|
5
|
+
from pydantic import BaseModel, ConfigDict
|
6
6
|
|
7
7
|
from classiq.interface.enum_utils import StrEnum
|
8
8
|
from classiq.interface.exceptions import ClassiqValueError
|
@@ -29,7 +29,7 @@ def optimization_parameter_type_from_string(param: str) -> OptimizationParameter
|
|
29
29
|
raise ClassiqValueError(f"Invalid OptimizationParameterType {param}")
|
30
30
|
|
31
31
|
|
32
|
-
class Constraints(BaseModel
|
32
|
+
class Constraints(BaseModel):
|
33
33
|
"""
|
34
34
|
Constraints for the quantum circuit synthesis engine.
|
35
35
|
|
@@ -51,6 +51,8 @@ class Constraints(BaseModel, extra=Extra.forbid):
|
|
51
51
|
the solution. Defaults to `NO_OPTIMIZATION`. See `OptimizationParameterType`
|
52
52
|
"""
|
53
53
|
|
54
|
+
model_config = ConfigDict(extra="forbid")
|
55
|
+
|
54
56
|
max_width: Optional[pydantic.PositiveInt] = pydantic.Field(
|
55
57
|
default=None,
|
56
58
|
description="Maximum number of qubits in generated quantum circuit",
|
@@ -51,7 +51,8 @@ class ClassiqBaseModel(VersionedModel, ABC):
|
|
51
51
|
default_factory=ExecutionPreferences
|
52
52
|
)
|
53
53
|
|
54
|
-
@pydantic.
|
54
|
+
@pydantic.field_validator("types")
|
55
|
+
@classmethod
|
55
56
|
def types_validator(cls, types: List[StructDeclaration]) -> List[StructDeclaration]:
|
56
57
|
if not is_list_unique([struct_type.name for struct_type in types]):
|
57
58
|
raise ClassiqValueError(TYPE_LIBRARY_DUPLICATED_TYPE_NAMES)
|