classiq 0.41.2__py3-none-any.whl → 0.42.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/applications/chemistry/chemistry_model_constructor.py +31 -31
- classiq/execution/execution_session.py +42 -3
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +16 -6
- classiq/interface/analyzer/result.py +2 -1
- classiq/interface/ast_node.py +2 -2
- classiq/interface/backend/pydantic_backend.py +1 -3
- classiq/interface/chemistry/fermionic_operator.py +17 -7
- classiq/interface/generator/amplitude_loading.py +12 -3
- classiq/interface/generator/application_apis/finance_declarations.py +22 -1
- classiq/interface/generator/expressions/atomic_expression_functions.py +2 -1
- classiq/interface/generator/expressions/enums/classical_enum.py +11 -0
- classiq/interface/generator/expressions/enums/ladder_operator.py +0 -10
- classiq/interface/generator/expressions/expression_constants.py +1 -0
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +14 -1
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +7 -2
- classiq/interface/generator/expressions/qmod_sized_proxy.py +8 -3
- classiq/interface/generator/expressions/qmod_struct_instance.py +12 -1
- classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +262 -195
- classiq/interface/generator/functions/builtins/internal_operators.py +1 -0
- classiq/interface/generator/functions/builtins/open_lib_functions.py +1645 -44
- classiq/interface/generator/functions/classical_type.py +21 -3
- classiq/interface/generator/generated_circuit_data.py +2 -0
- classiq/interface/generator/model/model.py +1 -1
- classiq/interface/{model → generator/model}/quantum_register.py +3 -0
- classiq/interface/helpers/classproperty.py +8 -0
- classiq/interface/ide/visual_model.py +68 -0
- classiq/interface/model/control.py +11 -1
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +3 -8
- classiq/interface/model/quantum_expressions/quantum_expression.py +1 -30
- classiq/interface/model/quantum_function_call.py +0 -12
- classiq/interface/model/validations/handles_validator.py +2 -7
- classiq/interface/server/routes.py +1 -0
- classiq/qmod/builtins/classical_execution_primitives.py +1 -1
- classiq/qmod/builtins/functions.py +83 -31
- classiq/qmod/builtins/operations.py +16 -1
- classiq/qmod/declaration_inferrer.py +28 -4
- classiq/qmod/pretty_print/pretty_printer.py +22 -2
- classiq/qmod/qmod_constant.py +2 -1
- classiq/qmod/qmod_parameter.py +9 -2
- classiq/qmod/quantum_expandable.py +35 -11
- classiq/qmod/quantum_function.py +6 -5
- classiq/qmod/symbolic.py +22 -1
- classiq/qmod/utilities.py +5 -5
- {classiq-0.41.2.dist-info → classiq-0.42.0.dist-info}/METADATA +1 -1
- {classiq-0.41.2.dist-info → classiq-0.42.0.dist-info}/RECORD +47 -46
- classiq/interface/model/call_synthesis_data.py +0 -57
- {classiq-0.41.2.dist-info → classiq-0.42.0.dist-info}/WHEEL +0 -0
@@ -6,6 +6,12 @@ from classiq.interface.chemistry.fermionic_operator import (
|
|
6
6
|
FermionicOperator,
|
7
7
|
SummedFermionicOperator,
|
8
8
|
)
|
9
|
+
from classiq.qmod.builtins.structs import (
|
10
|
+
MoleculeProblem as QmodMoleculeProblem,
|
11
|
+
Molecule as QmodMolecule,
|
12
|
+
ChemistryAtom as QmodChemistryAtom,
|
13
|
+
Position as QmodPosition,
|
14
|
+
)
|
9
15
|
from classiq.interface.chemistry.ground_state_problem import (
|
10
16
|
CHEMISTRY_PROBLEMS_TYPE,
|
11
17
|
HamiltonianProblem,
|
@@ -185,42 +191,36 @@ _HAE_GATE_MAPPING: Dict[str, QuantumFunctionCall] = {
|
|
185
191
|
}
|
186
192
|
|
187
193
|
|
188
|
-
def _atoms_to_qmod_atoms(atoms: List[Atom]) ->
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
")"
|
194
|
+
def _atoms_to_qmod_atoms(atoms: List[Atom]) -> List[QmodChemistryAtom]:
|
195
|
+
return [
|
196
|
+
QmodChemistryAtom(
|
197
|
+
element=Element[atom.symbol],
|
198
|
+
position=QmodPosition(
|
199
|
+
x=atom.x, # type:ignore[arg-type]
|
200
|
+
y=atom.y, # type:ignore[arg-type]
|
201
|
+
z=atom.z, # type:ignore[arg-type]
|
202
|
+
),
|
203
|
+
)
|
199
204
|
for atom in atoms
|
200
205
|
]
|
201
|
-
# fmt: on
|
202
|
-
return ",".join(atom_struct_literals)
|
203
206
|
|
204
207
|
|
205
208
|
def molecule_problem_to_qmod(
|
206
209
|
molecule_problem: MoleculeProblem,
|
207
|
-
) ->
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
f"remove_orbitals={molecule_problem.remove_orbitals}"
|
222
|
-
")")
|
223
|
-
# fmt: on
|
210
|
+
) -> QmodMoleculeProblem:
|
211
|
+
return QmodMoleculeProblem(
|
212
|
+
mapping=FermionMapping[molecule_problem.mapping.value.upper()],
|
213
|
+
z2_symmetries=molecule_problem.z2_symmetries, # type:ignore[arg-type]
|
214
|
+
molecule=QmodMolecule(
|
215
|
+
atoms=_atoms_to_qmod_atoms(
|
216
|
+
molecule_problem.molecule.atoms
|
217
|
+
), # type:ignore[arg-type]
|
218
|
+
spin=molecule_problem.molecule.spin, # type:ignore[arg-type]
|
219
|
+
charge=molecule_problem.molecule.charge, # type:ignore[arg-type]
|
220
|
+
),
|
221
|
+
freeze_core=molecule_problem.freeze_core, # type:ignore[arg-type]
|
222
|
+
remove_orbitals=molecule_problem.remove_orbitals, # type:ignore[arg-type]
|
223
|
+
)
|
224
224
|
|
225
225
|
|
226
226
|
def _fermionic_operator_to_qmod_ladder_ops(
|
@@ -271,7 +271,7 @@ def _hamiltonian_problem_to_qmod_fock_hamiltonian_problem(
|
|
271
271
|
|
272
272
|
def _convert_library_problem_to_qmod_problem(problem: CHEMISTRY_PROBLEMS_TYPE) -> str:
|
273
273
|
if isinstance(problem, MoleculeProblem):
|
274
|
-
return molecule_problem_to_qmod(problem)
|
274
|
+
return str(molecule_problem_to_qmod(problem))
|
275
275
|
elif isinstance(problem, HamiltonianProblem):
|
276
276
|
return _hamiltonian_problem_to_qmod_fock_hamiltonian_problem(problem)
|
277
277
|
else:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import json
|
2
|
-
from typing import Any, Callable, Dict, List, Optional, Union, cast
|
2
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast
|
3
3
|
|
4
4
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
5
5
|
from classiq.interface.executor.execution_result import ResultsCollection
|
@@ -24,7 +24,12 @@ from classiq.synthesis import SerializedQuantumProgram
|
|
24
24
|
|
25
25
|
Hamiltonian = Union[List[QmodPyStruct], List[PauliTerm]]
|
26
26
|
Program = Union[SerializedQuantumProgram, QuantumProgram]
|
27
|
-
|
27
|
+
ParsedExecutionParams = Dict[str, Union[float, int]]
|
28
|
+
ExecutionParameters = Optional[Union[ExecutionParams, List[ExecutionParams]]]
|
29
|
+
ParsedExecutionParameters = Optional[
|
30
|
+
Union[ParsedExecutionParams, List[ParsedExecutionParams]]
|
31
|
+
]
|
32
|
+
|
28
33
|
|
29
34
|
SAVE_RESULT = "\nsave({'result': result})\n"
|
30
35
|
|
@@ -52,8 +57,42 @@ def to_hamiltonian_str(hamiltonian: Hamiltonian) -> str:
|
|
52
57
|
)
|
53
58
|
|
54
59
|
|
60
|
+
def serialize(
|
61
|
+
item: Union[float, int, Tuple[int, ...], Tuple[float, ...]]
|
62
|
+
) -> Union[str, List]:
|
63
|
+
if isinstance(item, tuple):
|
64
|
+
return list(item)
|
65
|
+
return str(item)
|
66
|
+
|
67
|
+
|
68
|
+
def parse_params(params: ExecutionParams) -> ParsedExecutionParams:
|
69
|
+
result = {}
|
70
|
+
for key, values in params.items():
|
71
|
+
if isinstance(values, list):
|
72
|
+
for index, value in enumerate(values):
|
73
|
+
new_key = f"{key}_{index}"
|
74
|
+
result[new_key] = value
|
75
|
+
elif isinstance(values, (int, float)):
|
76
|
+
result[key] = values
|
77
|
+
else:
|
78
|
+
raise TypeError("Parameters were provided in un-supported format")
|
79
|
+
return result
|
80
|
+
|
81
|
+
|
55
82
|
def format_parameters(execution_params: ExecutionParameters) -> str:
|
56
|
-
|
83
|
+
parsed_parameters: ParsedExecutionParameters = None
|
84
|
+
if execution_params is None:
|
85
|
+
return ""
|
86
|
+
if isinstance(execution_params, dict):
|
87
|
+
parsed_parameters = parse_params(execution_params)
|
88
|
+
|
89
|
+
elif isinstance(execution_params, list):
|
90
|
+
parsed_parameters = [
|
91
|
+
parse_params(ep) if isinstance(ep, dict) else ep for ep in execution_params
|
92
|
+
]
|
93
|
+
|
94
|
+
execution_params = cast(ExecutionParams, parsed_parameters)
|
95
|
+
return json.dumps(execution_params, default=serialize, indent=2)
|
57
96
|
|
58
97
|
|
59
98
|
def create_estimate_execution_code(operation: str, **kwargs: Any) -> str:
|
classiq/interface/_version.py
CHANGED
@@ -2,7 +2,8 @@ from typing import Dict, List, Optional
|
|
2
2
|
|
3
3
|
import numpy
|
4
4
|
import pydantic
|
5
|
-
from pydantic import Field
|
5
|
+
from pydantic import Field, conint, constr
|
6
|
+
from typing_extensions import Annotated
|
6
7
|
|
7
8
|
from classiq.interface.backend.quantum_backend_providers import AnalyzerProviderVendor
|
8
9
|
from classiq.interface.chemistry.ground_state_problem import MoleculeProblem
|
@@ -17,6 +18,12 @@ from classiq.interface.helpers.custom_pydantic_types import PydanticNonEmptyStri
|
|
17
18
|
MAX_KB_OF_FILE = 500
|
18
19
|
MAX_FILE_LENGTH = MAX_KB_OF_FILE * 1024
|
19
20
|
|
21
|
+
MAX_QUBITS = 100
|
22
|
+
MIN_QUBITS = 0
|
23
|
+
MAX_COUNTS = 1000
|
24
|
+
MAX_NUM_CLIFFORD = 1000
|
25
|
+
MAX_NAME_LENGTH = 100
|
26
|
+
|
20
27
|
|
21
28
|
class AnalysisParams(pydantic.BaseModel):
|
22
29
|
qasm: PydanticNonEmptyString = Field(..., max_length=MAX_FILE_LENGTH)
|
@@ -40,13 +47,16 @@ class HardwareListParams(pydantic.BaseModel):
|
|
40
47
|
|
41
48
|
class AnalysisOptionalDevicesParams(HardwareListParams):
|
42
49
|
qubit_count: int = pydantic.Field(
|
43
|
-
default=...,
|
50
|
+
default=...,
|
51
|
+
description="number of qubits in the data",
|
52
|
+
ge=MIN_QUBITS,
|
53
|
+
le=MAX_QUBITS,
|
44
54
|
)
|
45
55
|
|
46
56
|
|
47
57
|
class GateNamsMapping(pydantic.BaseModel):
|
48
|
-
qasm_name: str
|
49
|
-
display_name: str
|
58
|
+
qasm_name: Annotated[str, constr(max_length=MAX_NAME_LENGTH)]
|
59
|
+
display_name: Annotated[str, constr(max_length=MAX_NAME_LENGTH)]
|
50
60
|
|
51
61
|
|
52
62
|
class LatexParams(AnalysisParams):
|
@@ -81,8 +91,8 @@ class CircuitAnalysisHardwareParams(AnalysisParams):
|
|
81
91
|
|
82
92
|
class AnalysisRBParams(pydantic.BaseModel):
|
83
93
|
hardware: str
|
84
|
-
counts: List[Dict[str, int]]
|
85
|
-
num_clifford: List[int]
|
94
|
+
counts: List[Dict[str, Annotated[int, conint(strict=True, gt=0, le=MAX_COUNTS)]]]
|
95
|
+
num_clifford: List[Annotated[int, conint(strict=True, gt=0, le=MAX_NUM_CLIFFORD)]]
|
86
96
|
|
87
97
|
|
88
98
|
class ChemistryGenerationParams(pydantic.BaseModel):
|
@@ -5,6 +5,7 @@ import pydantic
|
|
5
5
|
from pydantic import Field
|
6
6
|
from typing_extensions import Annotated
|
7
7
|
|
8
|
+
from classiq.interface.analyzer.analysis_params import MAX_FILE_LENGTH
|
8
9
|
from classiq.interface.helpers.custom_pydantic_types import PydanticNonEmptyString
|
9
10
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
10
11
|
|
@@ -38,7 +39,7 @@ class DataID(pydantic.BaseModel):
|
|
38
39
|
|
39
40
|
|
40
41
|
class QasmCode(pydantic.BaseModel):
|
41
|
-
code: str
|
42
|
+
code: str = Field(..., max_length=MAX_FILE_LENGTH)
|
42
43
|
|
43
44
|
|
44
45
|
class AnalysisStatus(StrEnum):
|
classiq/interface/ast_node.py
CHANGED
@@ -20,9 +20,9 @@ class SourceReference(HashablePydanticBaseModel):
|
|
20
20
|
f"file {os.path.basename(self.file_name)} " if self.file_name else ""
|
21
21
|
)
|
22
22
|
start_character_string = (
|
23
|
-
f" character {self.start_column}" if self.start_column else ""
|
23
|
+
f" character {self.start_column + 1}" if self.start_column > 0 else ""
|
24
24
|
)
|
25
|
-
return f"{file_string}line {self.start_line}{start_character_string}"
|
25
|
+
return f"{file_string}line {self.start_line + 1}{start_character_string}"
|
26
26
|
|
27
27
|
|
28
28
|
class ASTNode(HashablePydanticBaseModel):
|
@@ -40,9 +40,7 @@ else:
|
|
40
40
|
regex=f"[A-Za-z0-9]{{{_IONQ_API_KEY_LENGTH}}}"
|
41
41
|
)
|
42
42
|
|
43
|
-
PydanticAliceBobApiKeyType = pydantic.constr(
|
44
|
-
regex=f"[A-Za-z0-9]{{{_ALICE_BOB_API_KEY_LENGTH}}}"
|
45
|
-
)
|
43
|
+
PydanticAliceBobApiKeyType = pydantic.constr(min_length=1, strip_whitespace=True)
|
46
44
|
|
47
45
|
PydanticExecutionTimeout = pydantic.conint(gt=0, le=MAX_EXECUTION_TIMEOUT_SECONDS)
|
48
46
|
|
@@ -39,7 +39,10 @@ class FermionicOperator(HashablePydanticBaseModel):
|
|
39
39
|
"""
|
40
40
|
|
41
41
|
op_list: list = pydantic.Field(
|
42
|
-
description=
|
42
|
+
description=(
|
43
|
+
"A list of tuples each containing an index and a character; for "
|
44
|
+
"example [('+', 0), ('-', 1)]."
|
45
|
+
),
|
43
46
|
)
|
44
47
|
|
45
48
|
@staticmethod
|
@@ -51,20 +54,27 @@ class FermionicOperator(HashablePydanticBaseModel):
|
|
51
54
|
raise ClassiqValueError("Ladder operator should be a tuple.") from exc
|
52
55
|
if len(op) != 2:
|
53
56
|
raise ClassiqValueError(
|
54
|
-
"Ladder operator tuple should be of length two; for example (
|
57
|
+
"Ladder operator tuple should be of length two; for example ('+', 1)."
|
55
58
|
)
|
56
59
|
|
57
|
-
|
60
|
+
op_symbol = op[0]
|
61
|
+
if op_symbol == "LadderOperator.PLUS":
|
62
|
+
op_symbol = "+"
|
63
|
+
elif op_symbol == "LadderOperator.MINUS":
|
64
|
+
op_symbol = "-"
|
65
|
+
if op_symbol not in ("+", "-"):
|
58
66
|
raise ClassiqValueError(
|
59
|
-
"The first term in a ladder operator tuple indicates if its a raising
|
60
|
-
f"
|
67
|
+
f"The first term in a ladder operator tuple indicates if its a raising "
|
68
|
+
f"(LadderOperator.PLUS / '+') or lowering (LadderOperator.MINUS / '-') "
|
69
|
+
f"operator. Received {op_symbol}"
|
61
70
|
)
|
62
|
-
|
71
|
+
op_index = op[1]
|
72
|
+
if not isinstance(op_index, int):
|
63
73
|
raise ClassiqValueError(
|
64
74
|
"The second term in a ladder operator tuple indicates its index and should be of type int"
|
65
75
|
)
|
66
76
|
|
67
|
-
return
|
77
|
+
return (op_symbol, op_index)
|
68
78
|
|
69
79
|
@pydantic.validator("op_list")
|
70
80
|
def _validate_op_list(cls, op_list: list) -> list:
|
@@ -9,6 +9,7 @@ from classiq.interface.generator.arith.arithmetic_expression_validator import (
|
|
9
9
|
)
|
10
10
|
from classiq.interface.generator.arith.register_user_input import RegisterUserInput
|
11
11
|
from classiq.interface.generator.expressions.expression_constants import (
|
12
|
+
BOOLEAN_LITERALS,
|
12
13
|
FORBIDDEN_LITERALS,
|
13
14
|
SUPPORTED_FUNC_NAMES,
|
14
15
|
SUPPORTED_VAR_NAMES_REG,
|
@@ -36,6 +37,12 @@ class AmplitudeLoading(FunctionParams):
|
|
36
37
|
size: pydantic.PositiveInt = pydantic.Field(
|
37
38
|
description="The number of qubits of the amplitude input."
|
38
39
|
)
|
40
|
+
fraction_digits: pydantic.NonNegativeInt = pydantic.Field(
|
41
|
+
description="The number of fraction digits of the amplitude input."
|
42
|
+
)
|
43
|
+
is_signed: bool = pydantic.Field(
|
44
|
+
description="Whether the amplitude input has a sign qubit."
|
45
|
+
)
|
39
46
|
expression: PydanticExpressionStr = pydantic.Field(
|
40
47
|
description="The mathematical expression of the amplitude loading function."
|
41
48
|
)
|
@@ -64,8 +71,8 @@ class AmplitudeLoading(FunctionParams):
|
|
64
71
|
expression = values.get("expression", "")
|
65
72
|
literals = set(re.findall(SUPPORTED_VAR_NAMES_REG, expression))
|
66
73
|
|
67
|
-
not_allowed = literals.intersection(FORBIDDEN_LITERALS)
|
68
|
-
variables = literals.difference(SUPPORTED_FUNC_NAMES)
|
74
|
+
not_allowed = literals.intersection(FORBIDDEN_LITERALS) - BOOLEAN_LITERALS
|
75
|
+
variables = literals.difference(SUPPORTED_FUNC_NAMES) - BOOLEAN_LITERALS
|
69
76
|
if not_allowed:
|
70
77
|
raise ClassiqValueError(
|
71
78
|
f"The following names: {not_allowed} are not allowed"
|
@@ -89,5 +96,7 @@ class AmplitudeLoading(FunctionParams):
|
|
89
96
|
|
90
97
|
@property
|
91
98
|
def variable(self) -> str:
|
92
|
-
literals =
|
99
|
+
literals = (
|
100
|
+
set(re.findall(SUPPORTED_VAR_NAMES_REG, self.expression)) - BOOLEAN_LITERALS
|
101
|
+
)
|
93
102
|
return list(literals.difference(SUPPORTED_FUNC_NAMES))[0]
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from enum import Enum
|
2
|
-
from typing import Mapping
|
2
|
+
from typing import TYPE_CHECKING, Callable, Mapping
|
3
3
|
|
4
4
|
from classiq.interface.generator.expressions.expression import Expression
|
5
5
|
from classiq.interface.generator.functions.classical_function_declaration import (
|
@@ -21,6 +21,10 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
21
21
|
QuantumFunctionDeclaration,
|
22
22
|
)
|
23
23
|
|
24
|
+
if TYPE_CHECKING:
|
25
|
+
from classiq.qmod.builtins.structs import GaussianModel
|
26
|
+
from classiq.qmod.symbolic_expr import SymbolicExpr
|
27
|
+
|
24
28
|
FUNCTION_PORT_NAME = "func_port"
|
25
29
|
OBJECTIVE_PORT_NAME = "obj_port"
|
26
30
|
|
@@ -36,6 +40,23 @@ FINANCE_FUNCTION_PORT_SIZE_MAPPING: Mapping[FinanceModelType, str] = {
|
|
36
40
|
}
|
37
41
|
|
38
42
|
|
43
|
+
def _get_gaussian_size(finance_model: "GaussianModel") -> "SymbolicExpr":
|
44
|
+
from classiq.qmod.symbolic import floor, log, sum as sym_sum
|
45
|
+
|
46
|
+
return (
|
47
|
+
finance_model.num_qubits
|
48
|
+
+ finance_model.rhos.len
|
49
|
+
+ floor(log(sym_sum(finance_model.loss), 2))
|
50
|
+
+ 1
|
51
|
+
)
|
52
|
+
|
53
|
+
|
54
|
+
FINANCE_FUNCTION_PORT_SIZE_FUNCTION_MAPPING: Mapping[FinanceModelType, Callable] = {
|
55
|
+
FinanceModelType.Gaussian: _get_gaussian_size,
|
56
|
+
FinanceModelType.LogNormal: lambda finance_model: finance_model.num_qubits,
|
57
|
+
}
|
58
|
+
|
59
|
+
|
39
60
|
def _generate_finance_function(
|
40
61
|
finance_model: FinanceModelType,
|
41
62
|
) -> QuantumFunctionDeclaration:
|
@@ -1,8 +1,9 @@
|
|
1
1
|
from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
|
2
2
|
|
3
|
-
SUPPORTED_BUILTIN_FUNCTIONS =
|
3
|
+
SUPPORTED_BUILTIN_FUNCTIONS = ["len", "sum", "print"]
|
4
4
|
|
5
5
|
SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS = {
|
6
|
+
"do_subscript",
|
6
7
|
"hypercube_entangler_graph",
|
7
8
|
"grid_entangler_graph",
|
8
9
|
"qft_const_adder_phase",
|
@@ -1,4 +1,7 @@
|
|
1
1
|
import enum
|
2
|
+
from typing import Any, Mapping
|
3
|
+
|
4
|
+
from classiq.interface.helpers.classproperty import classproperty
|
2
5
|
|
3
6
|
|
4
7
|
class ClassicalEnum(int, enum.Enum):
|
@@ -7,3 +10,11 @@ class ClassicalEnum(int, enum.Enum):
|
|
7
10
|
|
8
11
|
def __repr__(self) -> str:
|
9
12
|
return str(self)
|
13
|
+
|
14
|
+
@classproperty
|
15
|
+
def type_name(cls) -> str: # noqa: N805
|
16
|
+
return "Enum"
|
17
|
+
|
18
|
+
@classproperty
|
19
|
+
def fields(cls) -> Mapping[str, Any]: # noqa: N805
|
20
|
+
return {i.name: i for i in cls} # type:ignore[attr-defined]
|
@@ -1,16 +1,6 @@
|
|
1
|
-
from typing_extensions import assert_never
|
2
|
-
|
3
1
|
from classiq.interface.generator.expressions.enums.classical_enum import ClassicalEnum
|
4
2
|
|
5
3
|
|
6
4
|
class LadderOperator(ClassicalEnum):
|
7
5
|
PLUS = 0
|
8
6
|
MINUS = 1
|
9
|
-
|
10
|
-
def __str__(self) -> str:
|
11
|
-
if self is LadderOperator.PLUS:
|
12
|
-
return "+"
|
13
|
-
elif self is LadderOperator.MINUS:
|
14
|
-
return "-"
|
15
|
-
else:
|
16
|
-
assert_never(self)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Optional, Tuple, Union
|
1
|
+
from typing import Any, Mapping, Optional, Tuple, Union
|
2
2
|
|
3
3
|
from classiq.interface.generator.expressions.expression import Expression
|
4
4
|
from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
|
@@ -56,6 +56,10 @@ class QmodQArrayProxy(QmodSizedProxy):
|
|
56
56
|
return self._slice[0] + start, self._slice[0] + end
|
57
57
|
return start, end
|
58
58
|
|
59
|
+
@property
|
60
|
+
def type_name(self) -> str:
|
61
|
+
return "Quantum array"
|
62
|
+
|
59
63
|
@property
|
60
64
|
def index(self) -> Optional[int]:
|
61
65
|
return self._index
|
@@ -81,9 +85,18 @@ class QmodQArrayProxy(QmodSizedProxy):
|
|
81
85
|
|
82
86
|
return HandleBinding(name=self._name)
|
83
87
|
|
88
|
+
@property
|
89
|
+
def fields(self) -> Mapping[str, Any]:
|
90
|
+
return {
|
91
|
+
"len": self.len,
|
92
|
+
}
|
93
|
+
|
84
94
|
def __len__(self) -> int:
|
85
95
|
if (slice_ := self.slice) is not None:
|
86
96
|
return slice_[1] - slice_[0]
|
87
97
|
elif self.index is not None:
|
88
98
|
return 1
|
89
99
|
return self._size
|
100
|
+
|
101
|
+
def __str__(self) -> str:
|
102
|
+
return str(self.handle)
|
@@ -20,11 +20,12 @@ class QmodQScalarProxy(Symbol, QmodSizedProxy):
|
|
20
20
|
|
21
21
|
|
22
22
|
class QmodQBitProxy(QmodQScalarProxy):
|
23
|
-
|
23
|
+
@property
|
24
|
+
def type_name(self) -> str:
|
25
|
+
return "Quantum bit"
|
24
26
|
|
25
27
|
|
26
28
|
class QmodQNumProxy(QmodQScalarProxy):
|
27
|
-
|
28
29
|
def __init__(
|
29
30
|
self, name: str, size: int, fraction_digits: int, is_signed: bool
|
30
31
|
) -> None:
|
@@ -32,6 +33,10 @@ class QmodQNumProxy(QmodQScalarProxy):
|
|
32
33
|
self._fraction_digits = fraction_digits
|
33
34
|
self._is_signed = is_signed
|
34
35
|
|
36
|
+
@property
|
37
|
+
def type_name(self) -> str:
|
38
|
+
return "Quantum numeric"
|
39
|
+
|
35
40
|
@property
|
36
41
|
def size(self) -> int:
|
37
42
|
return self._size
|
@@ -13,6 +13,13 @@ class QmodSizedProxy:
|
|
13
13
|
def __len__(self) -> int:
|
14
14
|
return self._size
|
15
15
|
|
16
|
+
def __str__(self) -> str:
|
17
|
+
return str(self.handle)
|
18
|
+
|
19
|
+
@property
|
20
|
+
def type_name(self) -> str:
|
21
|
+
raise NotImplementedError
|
22
|
+
|
16
23
|
@property
|
17
24
|
def handle(self) -> "HandleBinding":
|
18
25
|
raise ClassiqNotImplementedError("cannot compute handle")
|
@@ -23,6 +30,4 @@ class QmodSizedProxy:
|
|
23
30
|
|
24
31
|
@property
|
25
32
|
def fields(self) -> Mapping[str, Any]:
|
26
|
-
return {
|
27
|
-
"len": self.len,
|
28
|
-
}
|
33
|
+
return {}
|
@@ -16,9 +16,20 @@ class QmodStructInstance:
|
|
16
16
|
self.struct_declaration = struct_declaration
|
17
17
|
self._fields = fields
|
18
18
|
|
19
|
+
@property
|
20
|
+
def type_name(self) -> str:
|
21
|
+
return f"Struct {self.struct_declaration.name}"
|
22
|
+
|
19
23
|
@property
|
20
24
|
def fields(self) -> Mapping[str, Any]:
|
21
25
|
return types.MappingProxyType(self._fields)
|
22
26
|
|
27
|
+
def __str__(self) -> str:
|
28
|
+
return repr(self)
|
29
|
+
|
23
30
|
def __repr__(self) -> str:
|
24
|
-
|
31
|
+
fields = ", ".join(
|
32
|
+
f"{field_name}={field_value}"
|
33
|
+
for field_name, field_value in self._fields.items()
|
34
|
+
)
|
35
|
+
return f"{self.struct_declaration.name}({fields})"
|