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
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import List, Literal, Union
|
2
2
|
|
3
3
|
import pydantic
|
4
|
+
from pydantic import ConfigDict
|
4
5
|
|
5
6
|
from classiq.interface.chemistry.elements import ELEMENTS
|
6
7
|
from classiq.interface.exceptions import ClassiqValueError
|
@@ -20,7 +21,7 @@ class Atom(HashablePydanticBaseModel):
|
|
20
21
|
class Molecule(HashablePydanticBaseModel):
|
21
22
|
atoms: List[Atom] = pydantic.Field(
|
22
23
|
description="A list of atoms each containing the atoms symbol and its (x,y,z) location",
|
23
|
-
|
24
|
+
min_length=1,
|
24
25
|
)
|
25
26
|
spin: pydantic.NonNegativeInt = pydantic.Field(
|
26
27
|
default=1, description="spin of the molecule"
|
@@ -33,12 +34,17 @@ class Molecule(HashablePydanticBaseModel):
|
|
33
34
|
def atoms_type(self) -> List[AtomType]:
|
34
35
|
return [(atom.symbol, [atom.x, atom.y, atom.z]) for atom in self.atoms]
|
35
36
|
|
36
|
-
@
|
37
|
-
def
|
37
|
+
@classmethod
|
38
|
+
def _validate_atom(cls, atom: Union[AtomType, Atom]) -> Atom:
|
38
39
|
if isinstance(atom, (list, tuple)):
|
39
40
|
return cls._validate_old_atoms_type(atom)
|
40
41
|
return atom
|
41
42
|
|
43
|
+
@pydantic.field_validator("atoms", mode="before")
|
44
|
+
@classmethod
|
45
|
+
def _validate_atoms(cls, atoms: List[Union[AtomType, Atom]]) -> List[Atom]:
|
46
|
+
return [cls._validate_atom(atom) for atom in atoms]
|
47
|
+
|
42
48
|
@staticmethod
|
43
49
|
def _validate_old_atoms_type(atom: AtomType) -> Atom:
|
44
50
|
if len(atom) != 2:
|
@@ -62,5 +68,4 @@ class Molecule(HashablePydanticBaseModel):
|
|
62
68
|
|
63
69
|
return Atom(symbol=symbol, x=coordinate[0], y=coordinate[1], z=coordinate[2])
|
64
70
|
|
65
|
-
|
66
|
-
frozen = True
|
71
|
+
model_config = ConfigDict(frozen=True)
|
@@ -5,7 +5,6 @@ from typing import (
|
|
5
5
|
Dict,
|
6
6
|
List,
|
7
7
|
Optional,
|
8
|
-
Tuple,
|
9
8
|
Union,
|
10
9
|
cast,
|
11
10
|
)
|
@@ -14,6 +13,7 @@ import numpy as np
|
|
14
13
|
import pydantic
|
15
14
|
import sympy
|
16
15
|
from more_itertools import all_equal
|
16
|
+
from pydantic import ConfigDict
|
17
17
|
|
18
18
|
from classiq.interface.exceptions import ClassiqValueError
|
19
19
|
from classiq.interface.generator.function_params import validate_expression_str
|
@@ -42,8 +42,8 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
42
42
|
pauli_list: PydanticPauliList = pydantic.Field(
|
43
43
|
description="A list of tuples each containing a pauli string comprised of I,X,Y,Z characters and a complex coefficient; for example [('IZ', 0.1), ('XY', 0.2)].",
|
44
44
|
)
|
45
|
-
is_hermitian: bool = pydantic.Field(default=False)
|
46
45
|
has_complex_coefficients: bool = pydantic.Field(default=True)
|
46
|
+
is_hermitian: bool = pydantic.Field(default=False)
|
47
47
|
|
48
48
|
def show(self) -> str:
|
49
49
|
if self.is_hermitian:
|
@@ -55,16 +55,19 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
55
55
|
f"+({summand[1]:+.3f}) * {summand[0]}" for summand in self.pauli_list
|
56
56
|
)
|
57
57
|
|
58
|
-
@pydantic.
|
58
|
+
@pydantic.field_validator("pauli_list", mode="before")
|
59
|
+
@classmethod
|
59
60
|
def _validate_pauli_monomials(
|
60
|
-
cls,
|
61
|
-
) ->
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
61
|
+
cls, pauli_list: PydanticPauliList
|
62
|
+
) -> PydanticPauliList:
|
63
|
+
validated_pauli_list = []
|
64
|
+
for monomial in pauli_list:
|
65
|
+
# Validate the length
|
66
|
+
_PauliMonomialLengthValidator(monomial=monomial) # type: ignore[call-arg]
|
67
|
+
coeff = cls._validate_monomial_coefficient(monomial[1])
|
68
|
+
parsed_monomial = _PauliMonomialParser(string=monomial[0], coeff=coeff)
|
69
|
+
validated_pauli_list.append((parsed_monomial.string, parsed_monomial.coeff))
|
70
|
+
return validated_pauli_list
|
68
71
|
|
69
72
|
@staticmethod
|
70
73
|
def _validate_monomial_coefficient(
|
@@ -76,16 +79,38 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
76
79
|
coeff = str(coeff)
|
77
80
|
return coeff
|
78
81
|
|
79
|
-
@pydantic.
|
82
|
+
@pydantic.field_validator("pauli_list", mode="after")
|
83
|
+
@classmethod
|
80
84
|
def _validate_pauli_list(cls, pauli_list: PydanticPauliList) -> PydanticPauliList:
|
81
85
|
if not all_equal(len(summand[0]) for summand in pauli_list):
|
82
86
|
raise ClassiqValueError("Pauli strings have incompatible lengths.")
|
83
87
|
return pauli_list
|
84
88
|
|
85
|
-
@
|
89
|
+
@staticmethod
|
90
|
+
def check_if_hermitian(pauli_list: PydanticPauliList) -> bool:
|
91
|
+
if all(isinstance(summand[1], (float, int, complex)) for summand in pauli_list):
|
92
|
+
if all(np.isclose(summand[1].imag, 0) for summand in pauli_list): # type: ignore[union-attr]
|
93
|
+
return True
|
94
|
+
|
95
|
+
for pauli_string, coeff in pauli_list:
|
96
|
+
reverse_string = pauli_string[::-1]
|
97
|
+
reverse_found = False
|
98
|
+
for other_string, other_coeff in pauli_list:
|
99
|
+
if other_string == reverse_string and np.isclose(
|
100
|
+
coeff, other_coeff.conjugate() # type: ignore[union-attr]
|
101
|
+
):
|
102
|
+
reverse_found = True
|
103
|
+
break
|
104
|
+
if not reverse_found:
|
105
|
+
return False
|
106
|
+
return True
|
107
|
+
return False
|
108
|
+
|
109
|
+
@pydantic.model_validator(mode="before")
|
110
|
+
@classmethod
|
86
111
|
def _validate_hermitianity(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
87
112
|
pauli_list = values.get("pauli_list", [])
|
88
|
-
if
|
113
|
+
if PauliOperator.check_if_hermitian(pauli_list):
|
89
114
|
values["is_hermitian"] = all(
|
90
115
|
np.isclose(complex(summand[1]).real, summand[1])
|
91
116
|
for summand in pauli_list
|
@@ -93,7 +118,7 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
93
118
|
if values.get("is_hermitian", False):
|
94
119
|
values["has_complex_coefficients"] = False
|
95
120
|
values["pauli_list"] = [
|
96
|
-
(summand[0], complex(summand[1].real)
|
121
|
+
(summand[0], complex(summand[1]).real) for summand in pauli_list
|
97
122
|
]
|
98
123
|
else:
|
99
124
|
values["has_complex_coefficients"] = not all(
|
@@ -161,7 +186,7 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
161
186
|
(self._extend_pauli_string(pauli_string, num_extra_qubits), coeff)
|
162
187
|
for (pauli_string, coeff) in self.pauli_list
|
163
188
|
]
|
164
|
-
return self.
|
189
|
+
return self.model_copy(update={"pauli_list": new_pauli_list}, deep=True)
|
165
190
|
|
166
191
|
@staticmethod
|
167
192
|
def _reorder_pauli_string(
|
@@ -211,7 +236,7 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
211
236
|
(cls._reorder_pauli_string(pauli_string, order, new_num_qubits), coeff)
|
212
237
|
for pauli_string, coeff in operator.pauli_list
|
213
238
|
]
|
214
|
-
return cls(pauli_list=new_pauli_list)
|
239
|
+
return cls(pauli_list=new_pauli_list, is_hermitian=operator.is_hermitian)
|
215
240
|
|
216
241
|
@classmethod
|
217
242
|
def from_unzipped_lists(
|
@@ -234,8 +259,7 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
|
|
234
259
|
]
|
235
260
|
)
|
236
261
|
|
237
|
-
|
238
|
-
frozen = True
|
262
|
+
model_config = ConfigDict(frozen=True)
|
239
263
|
|
240
264
|
|
241
265
|
class PauliOperatorV1(HashablePydanticBaseModel):
|
@@ -259,16 +283,19 @@ class PauliOperatorV1(HashablePydanticBaseModel):
|
|
259
283
|
f"+({summand[1]:+.3f}) * {summand[0]}" for summand in self.pauli_list
|
260
284
|
)
|
261
285
|
|
262
|
-
@pydantic.
|
286
|
+
@pydantic.field_validator("pauli_list", mode="before")
|
287
|
+
@classmethod
|
263
288
|
def _validate_pauli_monomials(
|
264
|
-
cls,
|
265
|
-
) ->
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
289
|
+
cls, pauli_list: PydanticPauliList
|
290
|
+
) -> PydanticPauliList:
|
291
|
+
validated_pauli_list = []
|
292
|
+
for monomial in pauli_list:
|
293
|
+
# Validate the length
|
294
|
+
_PauliMonomialLengthValidator(monomial=monomial) # type: ignore[call-arg]
|
295
|
+
coeff = cls._validate_monomial_coefficient(monomial[1])
|
296
|
+
parsed_monomial = _PauliMonomialParser(string=monomial[0], coeff=coeff)
|
297
|
+
validated_pauli_list.append((parsed_monomial.string, parsed_monomial.coeff))
|
298
|
+
return validated_pauli_list
|
272
299
|
|
273
300
|
@staticmethod
|
274
301
|
def _validate_monomial_coefficient(
|
@@ -280,32 +307,34 @@ class PauliOperatorV1(HashablePydanticBaseModel):
|
|
280
307
|
coeff = str(coeff)
|
281
308
|
return coeff
|
282
309
|
|
283
|
-
@pydantic.
|
310
|
+
@pydantic.field_validator("pauli_list", mode="after")
|
311
|
+
@classmethod
|
284
312
|
def _validate_pauli_list(cls, pauli_list: PydanticPauliList) -> PydanticPauliList:
|
285
313
|
if not all_equal(len(summand[0]) for summand in pauli_list):
|
286
314
|
raise ClassiqValueError("Pauli strings have incompatible lengths.")
|
287
315
|
return pauli_list
|
288
316
|
|
289
|
-
@pydantic.
|
290
|
-
|
291
|
-
|
317
|
+
@pydantic.model_validator(mode="before")
|
318
|
+
@classmethod
|
319
|
+
def _validate_hermitianity(cls, v: Dict[str, Any]) -> Dict[str, Any]:
|
320
|
+
pauli_list = cast(PydanticPauliList, v.get("pauli_list"))
|
292
321
|
if all(isinstance(summand[1], complex) for summand in pauli_list):
|
293
|
-
|
322
|
+
v["is_hermitian"] = all(
|
294
323
|
np.isclose(complex(summand[1]).real, summand[1])
|
295
324
|
for summand in pauli_list
|
296
325
|
)
|
297
|
-
if
|
298
|
-
|
299
|
-
|
300
|
-
(summand[0], complex(summand[1].real)
|
326
|
+
if v["is_hermitian"]:
|
327
|
+
v["has_complex_coefficients"] = False
|
328
|
+
v["pauli_list"] = [
|
329
|
+
(summand[0], complex(summand[1]).real) for summand in pauli_list
|
301
330
|
]
|
302
331
|
else:
|
303
|
-
|
332
|
+
v["has_complex_coefficients"] = not all(
|
304
333
|
np.isclose(complex(summand[1]).real, summand[1])
|
305
334
|
for summand in pauli_list
|
306
335
|
if isinstance(summand[1], complex)
|
307
336
|
)
|
308
|
-
return
|
337
|
+
return v
|
309
338
|
|
310
339
|
def __mul__(self, coefficient: complex) -> "PauliOperatorV1":
|
311
340
|
multiplied_ising = [
|
@@ -361,7 +390,7 @@ class PauliOperatorV1(HashablePydanticBaseModel):
|
|
361
390
|
(self._extend_pauli_string(pauli_string, num_extra_qubits), coeff)
|
362
391
|
for (pauli_string, coeff) in self.pauli_list
|
363
392
|
]
|
364
|
-
return self.
|
393
|
+
return self.model_copy(update={"pauli_list": new_pauli_list}, deep=True)
|
365
394
|
|
366
395
|
@staticmethod
|
367
396
|
def _reorder_pauli_string(
|
@@ -434,8 +463,7 @@ class PauliOperatorV1(HashablePydanticBaseModel):
|
|
434
463
|
]
|
435
464
|
)
|
436
465
|
|
437
|
-
|
438
|
-
frozen = True
|
466
|
+
model_config = ConfigDict(frozen=True)
|
439
467
|
|
440
468
|
|
441
469
|
# This class validates the length of a monomial.
|
@@ -444,8 +472,7 @@ class _PauliMonomialLengthValidator:
|
|
444
472
|
monomial: PydanticPauliMonomial
|
445
473
|
|
446
474
|
|
447
|
-
|
448
|
-
class _PauliMonomialParser:
|
475
|
+
class _PauliMonomialParser(pydantic.BaseModel):
|
449
476
|
string: PydanticPauliMonomialStr
|
450
477
|
coeff: PydanticParameterComplexType
|
451
478
|
|
@@ -53,7 +53,8 @@ class MhtQaoaInput(BaseModel):
|
|
53
53
|
def is_valid_cost(self, cost: float) -> bool:
|
54
54
|
return True
|
55
55
|
|
56
|
-
@pydantic.
|
56
|
+
@pydantic.field_validator("plot_list")
|
57
|
+
@classmethod
|
57
58
|
def round_plot_list_times_and_validate(
|
58
59
|
cls, plot_list: List[PlotData]
|
59
60
|
) -> List[PlotData]:
|
@@ -15,8 +15,7 @@ ParameterValue = Union[float, int, str, None]
|
|
15
15
|
class FunctionDebugInfo(BaseModel):
|
16
16
|
name: str
|
17
17
|
# Parameters describe classical parameters passed to function
|
18
|
-
|
19
|
-
parameters: Dict[str, str] = Field(type=Dict[str, ParameterValue])
|
18
|
+
parameters: Dict[str, str]
|
20
19
|
level: OperationLevel
|
21
20
|
is_allocate_or_free: bool = Field(default=False)
|
22
21
|
is_inverse: bool = Field(default=False)
|
@@ -54,8 +53,8 @@ class DebugInfoCollection(BaseModel):
|
|
54
53
|
# Pydantic only started supporting UUID as keys in Pydantic V2
|
55
54
|
# See https://github.com/pydantic/pydantic/issues/2096#issuecomment-814860206
|
56
55
|
# For now, we use strings as keys in the raw data and use UUID in the wrapper logic
|
57
|
-
data: Dict[str, FunctionDebugInfo] = Field(
|
58
|
-
blackbox_data: Dict[str, FunctionDebugInfoInterface] = Field(
|
56
|
+
data: Dict[str, FunctionDebugInfo] = Field(default={})
|
57
|
+
blackbox_data: Dict[str, FunctionDebugInfoInterface] = Field(default={})
|
59
58
|
|
60
59
|
def __setitem__(self, key: UUID, value: FunctionDebugInfo) -> None:
|
61
60
|
self.data[str(key)] = value
|
@@ -0,0 +1,21 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
from classiq.interface.helpers.versioned_model import VersionedModel
|
4
|
+
|
5
|
+
|
6
|
+
class IQCCInitAuthData(VersionedModel):
|
7
|
+
auth_scope_id: str
|
8
|
+
auth_method_id: str
|
9
|
+
|
10
|
+
|
11
|
+
class IQCCInitAuthResponse(VersionedModel):
|
12
|
+
auth_url: str
|
13
|
+
token_id: str
|
14
|
+
|
15
|
+
|
16
|
+
class IQCCProbeAuthData(IQCCInitAuthData):
|
17
|
+
token_id: str
|
18
|
+
|
19
|
+
|
20
|
+
class IQCCProbeAuthResponse(VersionedModel):
|
21
|
+
auth_token: Optional[str]
|
@@ -1,28 +1,28 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from typing import List, Optional
|
3
3
|
|
4
|
-
from pydantic import BaseModel
|
4
|
+
from pydantic import BaseModel
|
5
5
|
|
6
6
|
from classiq.interface.jobs import JobStatus
|
7
7
|
|
8
8
|
|
9
|
-
class ExecutionJobDetailsV1(BaseModel, extra=
|
9
|
+
class ExecutionJobDetailsV1(BaseModel, extra="ignore"):
|
10
10
|
id: str
|
11
11
|
|
12
|
-
name: Optional[str]
|
12
|
+
name: Optional[str] = None
|
13
13
|
start_time: datetime
|
14
|
-
end_time: Optional[datetime]
|
14
|
+
end_time: Optional[datetime] = None
|
15
15
|
|
16
|
-
provider: Optional[str]
|
17
|
-
backend_name: Optional[str]
|
16
|
+
provider: Optional[str] = None
|
17
|
+
backend_name: Optional[str] = None
|
18
18
|
|
19
19
|
status: JobStatus
|
20
20
|
|
21
|
-
num_shots: Optional[int]
|
22
|
-
program_id: Optional[str]
|
21
|
+
num_shots: Optional[int] = None
|
22
|
+
program_id: Optional[str] = None
|
23
23
|
|
24
|
-
error: Optional[str]
|
24
|
+
error: Optional[str] = None
|
25
25
|
|
26
26
|
|
27
|
-
class ExecutionJobsQueryResultsV1(BaseModel, extra=
|
27
|
+
class ExecutionJobsQueryResultsV1(BaseModel, extra="ignore"):
|
28
28
|
results: List[ExecutionJobDetailsV1]
|
@@ -1,11 +1,12 @@
|
|
1
|
+
import datetime
|
1
2
|
from datetime import date
|
2
|
-
from typing import Any, Dict, List, Optional
|
3
|
+
from typing import Any, Dict, List, Optional, Union
|
3
4
|
|
4
5
|
import pydantic
|
5
|
-
from pydantic import
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
7
|
+
from pydantic_core.core_schema import ValidationInfo
|
6
8
|
|
7
9
|
from classiq.interface.enum_utils import StrEnum
|
8
|
-
from classiq.interface.exceptions import ClassiqValueError
|
9
10
|
|
10
11
|
|
11
12
|
class Granularity(StrEnum):
|
@@ -19,30 +20,44 @@ class CostScope(StrEnum):
|
|
19
20
|
organization = "organization"
|
20
21
|
|
21
22
|
|
22
|
-
class ExecutionCostForTimePeriod(
|
23
|
-
start: date =
|
24
|
-
description="The beginning of the time period for tasks usage and cost ("
|
25
|
-
"inclusive).",
|
23
|
+
class ExecutionCostForTimePeriod(BaseModel):
|
24
|
+
start: date = Field(
|
25
|
+
description="The beginning of the time period for tasks usage and cost (inclusive)."
|
26
26
|
)
|
27
|
-
end: date =
|
28
|
-
description="The end of the time period for tasks usage and cost (exclusive)."
|
27
|
+
end: date = Field(
|
28
|
+
description="The end of the time period for tasks usage and cost (exclusive)."
|
29
29
|
)
|
30
|
-
granularity: Granularity =
|
30
|
+
granularity: Granularity = Field(
|
31
31
|
description="Either MONTHLY or DAILY, or HOURLY.", default=Granularity.daily
|
32
32
|
)
|
33
|
-
cost_scope: CostScope =
|
33
|
+
cost_scope: CostScope = Field(
|
34
34
|
description="Either user or organization", default=CostScope.user
|
35
35
|
)
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
@pydantic.field_validator("start", mode="before")
|
38
|
+
@classmethod
|
39
|
+
def validate_start_date(cls, start_date: Union[datetime.datetime, date]) -> date:
|
40
|
+
if isinstance(start_date, datetime.datetime):
|
41
|
+
return start_date.date()
|
42
|
+
return start_date
|
43
|
+
|
44
|
+
@pydantic.field_validator("end", mode="before")
|
45
|
+
@classmethod
|
46
|
+
def validate_date_and_date_order(
|
47
|
+
cls, v: Union[date, datetime.datetime], info: ValidationInfo
|
48
|
+
) -> date:
|
49
|
+
if isinstance(v, datetime.datetime):
|
50
|
+
v = v.date()
|
51
|
+
if "start" in info.data and v <= info.data["start"]:
|
52
|
+
raise ValueError('"end" date should be after "start" date')
|
44
53
|
return v
|
45
54
|
|
55
|
+
def dict(self, **kwargs: Any) -> Dict[str, Any]:
|
56
|
+
data = super().model_dump(**kwargs)
|
57
|
+
data["start"] = self.start.strftime("%Y-%m-%d")
|
58
|
+
data["end"] = self.end.strftime("%Y-%m-%d")
|
59
|
+
return data
|
60
|
+
|
46
61
|
|
47
62
|
"""The following models describe the aws response model and based on this schema:
|
48
63
|
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ce.html#CostExplorer.Client.get_cost_and_usage"""
|
@@ -65,8 +80,10 @@ class Total(pydantic.BaseModel):
|
|
65
80
|
class ExecutedTaskForPeriodItem(pydantic.BaseModel):
|
66
81
|
TimePeriod: TimePeriod
|
67
82
|
Total: Total
|
68
|
-
Groups: Optional[List]
|
69
|
-
Estimated: Optional[bool]
|
83
|
+
Groups: Optional[List] = None
|
84
|
+
Estimated: Optional[bool] = None
|
85
|
+
|
86
|
+
model_config = ConfigDict(extra="forbid")
|
70
87
|
|
71
88
|
|
72
89
|
class ExecutionCostForTimePeriodResponse(pydantic.BaseModel):
|
@@ -57,9 +57,9 @@ class ExecutionJobDetails(VersionedModel):
|
|
57
57
|
status: JobStatus
|
58
58
|
|
59
59
|
num_shots: Optional[int]
|
60
|
-
program_id: Optional[str]
|
60
|
+
program_id: Optional[str] = Field(default=None)
|
61
61
|
|
62
|
-
error: Optional[str]
|
62
|
+
error: Optional[str] = Field(default=None)
|
63
63
|
|
64
64
|
|
65
65
|
class ExecutionJobsQueryResults(VersionedModel):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import Any, List, Literal, Union
|
2
2
|
|
3
|
-
from pydantic import BaseModel, Field
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field
|
4
4
|
from typing_extensions import Annotated, TypeAlias
|
5
5
|
|
6
6
|
from classiq.interface.enum_utils import StrEnum
|
@@ -85,7 +85,7 @@ class TaggedIQAEResult(BaseModel):
|
|
85
85
|
class TaggedUnstructured(BaseModel):
|
86
86
|
value_type: Literal[SavedResultValueType.Unstructured]
|
87
87
|
name: str
|
88
|
-
value: Any
|
88
|
+
value: Any = None
|
89
89
|
|
90
90
|
|
91
91
|
SavedResult = Annotated[
|
@@ -109,3 +109,5 @@ ResultsCollection: TypeAlias = List[SavedResult]
|
|
109
109
|
|
110
110
|
class ExecuteGeneratedCircuitResults(VersionedModel):
|
111
111
|
results: ResultsCollection
|
112
|
+
|
113
|
+
model_config = ConfigDict(extra="forbid")
|
@@ -14,6 +14,6 @@ class IQAEIterationData(BaseModel):
|
|
14
14
|
|
15
15
|
class IQAEResult(VersionedModel, QmodPyObject):
|
16
16
|
estimation: float
|
17
|
-
confidence_interval: List[float] = Field(
|
17
|
+
confidence_interval: List[float] = Field(min_length=2, max_length=2)
|
18
18
|
iterations_data: List[IQAEIterationData]
|
19
19
|
warnings: List[str]
|
@@ -1,7 +1,8 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import List, Optional
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
from pydantic import BaseModel
|
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
|
@@ -53,11 +54,12 @@ class OptimizerPreferences(BaseModel):
|
|
53
54
|
description="If True, the optimizer will not compute the variance of the ansatz.",
|
54
55
|
)
|
55
56
|
|
56
|
-
@pydantic.
|
57
|
+
@pydantic.field_validator("tolerance", mode="before")
|
58
|
+
@classmethod
|
57
59
|
def check_tolerance(
|
58
|
-
cls, tolerance: Optional[pydantic.PositiveFloat],
|
60
|
+
cls, tolerance: Optional[pydantic.PositiveFloat], info: ValidationInfo
|
59
61
|
) -> Optional[pydantic.PositiveFloat]:
|
60
|
-
optimizer_type =
|
62
|
+
optimizer_type = info.data.get("type")
|
61
63
|
if tolerance is not None and optimizer_type == OptimizerType.SPSA:
|
62
64
|
raise ClassiqValueError("No tolerance param for SPSA optimizer")
|
63
65
|
|
@@ -66,11 +68,12 @@ class OptimizerPreferences(BaseModel):
|
|
66
68
|
|
67
69
|
return tolerance
|
68
70
|
|
69
|
-
@pydantic.
|
71
|
+
@pydantic.field_validator("step_size", mode="before")
|
72
|
+
@classmethod
|
70
73
|
def check_step_size(
|
71
|
-
cls, step_size: Optional[pydantic.PositiveFloat],
|
74
|
+
cls, step_size: Optional[pydantic.PositiveFloat], info: ValidationInfo
|
72
75
|
) -> Optional[pydantic.PositiveFloat]:
|
73
|
-
optimizer_type =
|
76
|
+
optimizer_type = info.data.get("name")
|
74
77
|
if step_size is not None and optimizer_type not in (
|
75
78
|
OptimizerType.L_BFGS_B,
|
76
79
|
OptimizerType.ADAM,
|
@@ -109,11 +112,12 @@ class CombinatorialOptimizer(OptimizerPreferences):
|
|
109
112
|
description="Whether to check if all the solutions satisfy the constraints",
|
110
113
|
)
|
111
114
|
|
112
|
-
@pydantic.
|
115
|
+
@pydantic.field_validator("alpha_cvar", mode="before")
|
116
|
+
@classmethod
|
113
117
|
def check_alpha_cvar(
|
114
|
-
cls, alpha_cvar: Optional[PydanticAlphaParamCVAR],
|
118
|
+
cls, alpha_cvar: Optional[PydanticAlphaParamCVAR], info: ValidationInfo
|
115
119
|
) -> Optional[PydanticAlphaParamCVAR]:
|
116
|
-
cost_type =
|
120
|
+
cost_type = info.data.get("cost_type")
|
117
121
|
if alpha_cvar is not None and cost_type != CostType.CVAR:
|
118
122
|
raise ClassiqValueError("Use CVAR params only for CostType.CVAR.")
|
119
123
|
|
@@ -4,7 +4,8 @@ from pathlib import Path
|
|
4
4
|
from typing import Any, Dict, Optional, Tuple, Union
|
5
5
|
|
6
6
|
import pydantic
|
7
|
-
from pydantic import BaseModel
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
8
|
+
from pydantic_core.core_schema import ValidationInfo
|
8
9
|
|
9
10
|
from classiq.interface.backend.ionq.ionq_quantum_program import IonqQuantumCircuit
|
10
11
|
from classiq.interface.backend.pydantic_backend import PydanticArgumentNameType
|
@@ -31,17 +32,18 @@ class QuantumBaseCode(BaseModel):
|
|
31
32
|
..., description="The textual representation of the program"
|
32
33
|
)
|
33
34
|
|
34
|
-
@pydantic.
|
35
|
+
@pydantic.field_validator("code")
|
36
|
+
@classmethod
|
35
37
|
def load_quantum_program(
|
36
|
-
cls, code: Union[CodeType, IonqQuantumCircuit], values:
|
38
|
+
cls, code: Union[CodeType, IonqQuantumCircuit], values: ValidationInfo
|
37
39
|
) -> CodeType:
|
38
|
-
syntax = values.get("syntax")
|
40
|
+
syntax = values.data.get("syntax")
|
39
41
|
if isinstance(code, IonqQuantumCircuit):
|
40
42
|
if syntax != QuantumInstructionSet.IONQ:
|
41
43
|
raise ClassiqValueError(
|
42
44
|
f"Invalid code type {type(code)} for syntax: {syntax}"
|
43
45
|
)
|
44
|
-
return code.
|
46
|
+
return code.model_dump_json()
|
45
47
|
|
46
48
|
return code
|
47
49
|
|
@@ -56,41 +58,44 @@ class QuantumCode(QuantumBaseCode):
|
|
56
58
|
description="The map of outputs to their qubits in the circuit.",
|
57
59
|
)
|
58
60
|
registers_initialization: Optional[RegistersInitialization] = pydantic.Field(
|
59
|
-
|
61
|
+
default=None,
|
60
62
|
description="Initial conditions for the different registers in the circuit.",
|
61
63
|
)
|
62
64
|
synthesis_execution_data: Optional[ExecutionData] = pydantic.Field(default=None)
|
63
65
|
synthesis_execution_arguments: Arguments = pydantic.Field(default_factory=dict)
|
66
|
+
model_config = ConfigDict(validate_assignment=True)
|
64
67
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
@pydantic.validator("arguments")
|
68
|
+
@pydantic.field_validator("arguments", mode="before")
|
69
|
+
@classmethod
|
69
70
|
def validate_arguments(
|
70
|
-
cls, arguments: MultipleArguments,
|
71
|
+
cls, arguments: MultipleArguments, info: ValidationInfo
|
71
72
|
) -> MultipleArguments:
|
72
|
-
if arguments and
|
73
|
+
if arguments and info.data.get("syntax") not in (
|
73
74
|
QuantumInstructionSet.QSHARP,
|
74
75
|
QuantumInstructionSet.QASM,
|
75
76
|
):
|
76
77
|
raise ClassiqValueError("Only QASM or Q# programs support arguments")
|
77
78
|
|
78
|
-
if
|
79
|
+
if (
|
80
|
+
info.data.get("syntax") == QuantumInstructionSet.QSHARP
|
81
|
+
and len(arguments) > 1
|
82
|
+
):
|
79
83
|
raise ClassiqValueError(
|
80
84
|
f"Q# programs supports only one group of arguments. {len(arguments)} given"
|
81
85
|
)
|
82
86
|
|
83
87
|
return arguments
|
84
88
|
|
85
|
-
@pydantic.
|
89
|
+
@pydantic.field_validator("synthesis_execution_data")
|
90
|
+
@classmethod
|
86
91
|
def validate_synthesis_execution_data(
|
87
92
|
cls,
|
88
93
|
synthesis_execution_data: Optional[ExecutionData],
|
89
|
-
values:
|
94
|
+
values: ValidationInfo,
|
90
95
|
) -> Optional[ExecutionData]:
|
91
96
|
if (
|
92
97
|
synthesis_execution_data is not None
|
93
|
-
and values.get("syntax") is not QuantumInstructionSet.QASM
|
98
|
+
and values.data.get("syntax") is not QuantumInstructionSet.QASM
|
94
99
|
):
|
95
100
|
raise ClassiqValueError("Only QASM supports the requested configuration")
|
96
101
|
|