classiq 0.41.1__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.1.dist-info → classiq-0.42.0.dist-info}/METADATA +1 -1
- {classiq-0.41.1.dist-info → classiq-0.42.0.dist-info}/RECORD +47 -46
- classiq/interface/model/call_synthesis_data.py +0 -57
- {classiq-0.41.1.dist-info → classiq-0.42.0.dist-info}/WHEEL +0 -0
@@ -7,6 +7,7 @@ from sympy import IndexedBase, Symbol
|
|
7
7
|
from typing_extensions import Annotated
|
8
8
|
|
9
9
|
from classiq.interface.ast_node import HashableASTNode
|
10
|
+
from classiq.interface.generator.expressions.enums.classical_enum import ClassicalEnum
|
10
11
|
from classiq.interface.generator.expressions.enums.ladder_operator import (
|
11
12
|
LadderOperator as LadderOperatorEnum,
|
12
13
|
)
|
@@ -39,6 +40,13 @@ class ClassicalType(HashableASTNode):
|
|
39
40
|
class Config:
|
40
41
|
extra = Extra.forbid
|
41
42
|
|
43
|
+
def __str__(self) -> str:
|
44
|
+
return str(type(self).__name__)
|
45
|
+
|
46
|
+
|
47
|
+
class EnumType(ClassicalType):
|
48
|
+
pass
|
49
|
+
|
42
50
|
|
43
51
|
class Integer(ClassicalType):
|
44
52
|
kind: Literal["int"]
|
@@ -69,7 +77,7 @@ class Real(ClassicalType):
|
|
69
77
|
|
70
78
|
@property
|
71
79
|
def default_value(self) -> float:
|
72
|
-
return 0
|
80
|
+
return 0.0
|
73
81
|
|
74
82
|
@pydantic.root_validator(pre=True)
|
75
83
|
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
@@ -122,7 +130,7 @@ class ClassicalList(ClassicalType):
|
|
122
130
|
return CArray[self.element_type.qmod_type] # type:ignore[name-defined]
|
123
131
|
|
124
132
|
|
125
|
-
class Pauli(
|
133
|
+
class Pauli(EnumType):
|
126
134
|
kind: Literal["pauli"]
|
127
135
|
|
128
136
|
@property
|
@@ -187,6 +195,14 @@ class ClassicalArray(ClassicalType):
|
|
187
195
|
def _set_kind(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
188
196
|
return values_with_discriminator(values, "kind", "array")
|
189
197
|
|
198
|
+
@property
|
199
|
+
def qmod_type(self) -> type:
|
200
|
+
from classiq.qmod.qmod_parameter import CArray
|
201
|
+
|
202
|
+
return CArray[
|
203
|
+
self.element_type.qmod_type, self.size # type:ignore[name-defined]
|
204
|
+
]
|
205
|
+
|
190
206
|
|
191
207
|
class OpaqueHandle(ClassicalType):
|
192
208
|
@property
|
@@ -226,7 +242,7 @@ class IQAERes(OpaqueHandle):
|
|
226
242
|
return values_with_discriminator(values, "kind", "iqae_result")
|
227
243
|
|
228
244
|
|
229
|
-
class LadderOperator(
|
245
|
+
class LadderOperator(EnumType):
|
230
246
|
kind: Literal["ladder_operator"]
|
231
247
|
|
232
248
|
@property
|
@@ -263,6 +279,8 @@ ConcreteClassicalType = Annotated[
|
|
263
279
|
ClassicalList.update_forward_refs()
|
264
280
|
ClassicalArray.update_forward_refs()
|
265
281
|
|
282
|
+
PythonClassicalTypes = (int, float, bool, list, CStructBase, ClassicalEnum)
|
283
|
+
|
266
284
|
|
267
285
|
def as_symbolic(symbols: Dict[str, ClassicalType]) -> Dict[str, RuntimeExpression]:
|
268
286
|
return {
|
@@ -98,6 +98,8 @@ class FunctionDebugInfo(pydantic.BaseModel):
|
|
98
98
|
generated_function: Optional[GeneratedFunction]
|
99
99
|
children: List["FunctionDebugInfo"]
|
100
100
|
relative_qubits: Tuple[int, ...]
|
101
|
+
absolute_qubits: Optional[Tuple[int, ...]]
|
102
|
+
is_basis_gate: Optional[bool]
|
101
103
|
|
102
104
|
@property
|
103
105
|
def registers(self) -> List[GeneratedRegister]:
|
@@ -16,6 +16,7 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
16
16
|
)
|
17
17
|
from classiq.interface.generator.model.constraints import Constraints
|
18
18
|
from classiq.interface.generator.model.preferences.preferences import Preferences
|
19
|
+
from classiq.interface.generator.model.quantum_register import QReg, QRegGenericAlias
|
19
20
|
from classiq.interface.generator.quantum_function_call import (
|
20
21
|
SUFFIX_RANDOMIZER,
|
21
22
|
SynthesisQuantumFunctionCall,
|
@@ -26,7 +27,6 @@ from classiq.interface.generator.types.struct_declaration import StructDeclarati
|
|
26
27
|
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
27
28
|
from classiq.interface.helpers.validation_helpers import is_list_unique
|
28
29
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
29
|
-
from classiq.interface.model.quantum_register import QReg, QRegGenericAlias
|
30
30
|
|
31
31
|
from classiq import ForeignFunctionDefinition as SynthesisForeignFunctionDefinition
|
32
32
|
from classiq.exceptions import ClassiqValueError
|
@@ -87,6 +87,9 @@ class QReg:
|
|
87
87
|
raise ClassiqQRegError(f"Cannot create {size} new qubits")
|
88
88
|
self._qubits = [Qubit() for _ in range(size)]
|
89
89
|
|
90
|
+
def __hash__(self) -> int:
|
91
|
+
return super.__hash__(self)
|
92
|
+
|
90
93
|
@classmethod
|
91
94
|
def _from_qubits(cls, qubits: List[Qubit]) -> "QReg":
|
92
95
|
if (
|
@@ -0,0 +1,68 @@
|
|
1
|
+
from typing import Dict, List, Optional, Tuple
|
2
|
+
|
3
|
+
import pydantic
|
4
|
+
|
5
|
+
from classiq.interface.generator.hardware.hardware_data import SynthesisHardwareData
|
6
|
+
from classiq.interface.helpers.versioned_model import VersionedModel
|
7
|
+
|
8
|
+
from classiq._internals.enum_utils import StrEnum
|
9
|
+
|
10
|
+
|
11
|
+
class OperationLevel(StrEnum):
|
12
|
+
USER_DEFINED = "USER_DEFINED"
|
13
|
+
ENGINE_GENERATED = "ENGINE_GENERATED"
|
14
|
+
BASIS_GATE = "BASIS_GATE"
|
15
|
+
UNKNOWN = "UNKNOWN"
|
16
|
+
|
17
|
+
|
18
|
+
class OperationType(StrEnum):
|
19
|
+
REGULAR = "REGULAR"
|
20
|
+
VAR_INITIALIZATION = "VAR_INITIALIZATION"
|
21
|
+
BIND = "BIND"
|
22
|
+
|
23
|
+
|
24
|
+
class OperationData(pydantic.BaseModel):
|
25
|
+
approximated_depth: Optional[int]
|
26
|
+
width: int
|
27
|
+
gate_count: Dict[str, int] = pydantic.Field(default_factory=dict)
|
28
|
+
|
29
|
+
|
30
|
+
class ProgramData(pydantic.BaseModel):
|
31
|
+
hardware_data: SynthesisHardwareData
|
32
|
+
|
33
|
+
|
34
|
+
class OperationParameter(pydantic.BaseModel):
|
35
|
+
label: str
|
36
|
+
value: Optional[float]
|
37
|
+
|
38
|
+
|
39
|
+
class OperationLink(pydantic.BaseModel):
|
40
|
+
label: str
|
41
|
+
qubits: Tuple[int, ...]
|
42
|
+
type: str
|
43
|
+
|
44
|
+
|
45
|
+
class OperationLinks(pydantic.BaseModel):
|
46
|
+
inputs: List[OperationLink]
|
47
|
+
outputs: List[OperationLink]
|
48
|
+
|
49
|
+
|
50
|
+
class Operation(pydantic.BaseModel):
|
51
|
+
name: str
|
52
|
+
children: List["Operation"]
|
53
|
+
operation_data: Optional[OperationData]
|
54
|
+
operation_links: OperationLinks
|
55
|
+
control_qubits: Tuple[int, ...] = pydantic.Field(default_factory=tuple)
|
56
|
+
auxiliary_qubits: Tuple[int, ...]
|
57
|
+
target_qubits: Tuple[int, ...]
|
58
|
+
parameters: List[OperationParameter] = pydantic.Field(default_factory=list)
|
59
|
+
operation_level: OperationLevel
|
60
|
+
# This field is meant to identify unique operations, such as variable initialization
|
61
|
+
# These will be visualized differently. We don't identify them yet, though, so
|
62
|
+
# we always set this field to be REGULAR
|
63
|
+
operation_type: OperationType = pydantic.Field(default=OperationType.REGULAR)
|
64
|
+
|
65
|
+
|
66
|
+
class ProgramVisualModel(VersionedModel):
|
67
|
+
main_operation: Operation
|
68
|
+
program_data: ProgramData
|
@@ -1,5 +1,7 @@
|
|
1
1
|
from typing import TYPE_CHECKING, Literal
|
2
2
|
|
3
|
+
import pydantic
|
4
|
+
|
3
5
|
from classiq.interface.model.quantum_expressions.quantum_expression import (
|
4
6
|
QuantumExpressionOperation,
|
5
7
|
)
|
@@ -10,5 +12,13 @@ if TYPE_CHECKING:
|
|
10
12
|
|
11
13
|
class Control(QuantumExpressionOperation):
|
12
14
|
kind: Literal["Control"]
|
13
|
-
|
14
15
|
body: "StatementBlock"
|
16
|
+
|
17
|
+
_ctrl_state: str = pydantic.PrivateAttr(default="")
|
18
|
+
|
19
|
+
@property
|
20
|
+
def ctrl_state(self) -> str:
|
21
|
+
return self._ctrl_state
|
22
|
+
|
23
|
+
def set_ctrl_state(self, ctrl_state: str) -> None:
|
24
|
+
self._ctrl_state = ctrl_state
|
@@ -22,9 +22,7 @@ MULTI_VARS_UNSUPPORTED_ERROR = (
|
|
22
22
|
"Amplitude Loading with more than one input variable is unsupported."
|
23
23
|
)
|
24
24
|
|
25
|
-
|
26
|
-
"Amplitude Loading input variable should be a fixed-point number between 0 and 1"
|
27
|
-
)
|
25
|
+
VAR_TYPE_ILLEGAL = "Amplitude Loading input variable should be a quantum numeric"
|
28
26
|
|
29
27
|
|
30
28
|
class AmplitudeLoadingOperation(QuantumAssignmentOperation):
|
@@ -55,11 +53,8 @@ class AmplitudeLoadingOperation(QuantumAssignmentOperation):
|
|
55
53
|
if len(var_types) != 1:
|
56
54
|
raise ClassiqValueError(MULTI_VARS_UNSUPPORTED_ERROR)
|
57
55
|
var_type = list(var_types.values())[0]
|
58
|
-
if not (
|
59
|
-
|
60
|
-
and var_type.fraction_digits_value == var_type.size_in_bits
|
61
|
-
):
|
62
|
-
raise ClassiqValueError(VAR_DOMAIN_ILLEGAL)
|
56
|
+
if not isinstance(var_type, QuantumNumeric):
|
57
|
+
raise ClassiqValueError(VAR_TYPE_ILLEGAL)
|
63
58
|
super().initialize_var_types(var_types, machine_precision)
|
64
59
|
|
65
60
|
@classmethod
|
@@ -1,16 +1,9 @@
|
|
1
1
|
import abc
|
2
|
-
import
|
3
|
-
from typing import Dict, List, Mapping, Optional, Set, Union
|
2
|
+
from typing import Dict, List, Mapping, Optional, Union
|
4
3
|
|
5
4
|
import pydantic
|
6
5
|
|
7
|
-
from classiq.interface.generator.arith.arithmetic_expression_validator import (
|
8
|
-
DEFAULT_SUPPORTED_FUNC_NAMES,
|
9
|
-
)
|
10
6
|
from classiq.interface.generator.expressions.expression import Expression
|
11
|
-
from classiq.interface.generator.expressions.sympy_supported_expressions import (
|
12
|
-
SYMPY_SUPPORTED_EXPRESSIONS,
|
13
|
-
)
|
14
7
|
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
15
8
|
from classiq.interface.model.handle_binding import (
|
16
9
|
HandleBinding,
|
@@ -21,28 +14,6 @@ from classiq.interface.model.quantum_statement import QuantumOperation
|
|
21
14
|
from classiq.interface.model.quantum_type import QuantumType
|
22
15
|
|
23
16
|
|
24
|
-
class VarRefCollector(ast.NodeVisitor):
|
25
|
-
def __init__(self) -> None:
|
26
|
-
self.var_names: Set[str] = set()
|
27
|
-
|
28
|
-
def generic_visit(self, node: ast.AST) -> None:
|
29
|
-
if isinstance(node, ast.Name) and node.id not in set(
|
30
|
-
SYMPY_SUPPORTED_EXPRESSIONS
|
31
|
-
) | set(DEFAULT_SUPPORTED_FUNC_NAMES):
|
32
|
-
self.var_names.add(node.id)
|
33
|
-
super().generic_visit(node)
|
34
|
-
|
35
|
-
|
36
|
-
class VarRefTransformer(ast.NodeTransformer):
|
37
|
-
def __init__(self, var_mapping: Dict[str, str]) -> None:
|
38
|
-
self.var_mapping = var_mapping
|
39
|
-
|
40
|
-
def visit_Name(self, node: ast.Name) -> ast.Name:
|
41
|
-
if node.id in self.var_mapping:
|
42
|
-
node.id = self.var_mapping[node.id]
|
43
|
-
return node
|
44
|
-
|
45
|
-
|
46
17
|
class QuantumExpressionOperation(QuantumOperation):
|
47
18
|
expression: Expression = pydantic.Field()
|
48
19
|
_var_handles: List[HandleBinding] = pydantic.PrivateAttr(
|
@@ -12,7 +12,6 @@ from classiq.interface.generator.functions.function_declaration import (
|
|
12
12
|
from classiq.interface.generator.functions.port_declaration import (
|
13
13
|
PortDeclarationDirection,
|
14
14
|
)
|
15
|
-
from classiq.interface.model.call_synthesis_data import CallSynthesisData
|
16
15
|
from classiq.interface.model.handle_binding import (
|
17
16
|
HandleBinding,
|
18
17
|
SlicedHandleBinding,
|
@@ -143,10 +142,6 @@ class QuantumFunctionCall(QuantumOperation):
|
|
143
142
|
default=None
|
144
143
|
)
|
145
144
|
|
146
|
-
_synthesis_data: CallSynthesisData = pydantic.PrivateAttr(
|
147
|
-
default_factory=CallSynthesisData
|
148
|
-
)
|
149
|
-
|
150
145
|
@property
|
151
146
|
def func_decl(self) -> QuantumFunctionDeclaration:
|
152
147
|
if self._func_decl is None:
|
@@ -282,13 +277,6 @@ class QuantumFunctionCall(QuantumOperation):
|
|
282
277
|
if isinstance(qlambda, QuantumLambdaFunction):
|
283
278
|
qlambda.set_op_decl(op_decl)
|
284
279
|
|
285
|
-
@property
|
286
|
-
def synthesis_data(self) -> CallSynthesisData:
|
287
|
-
return self._synthesis_data
|
288
|
-
|
289
|
-
def merge_synthesis_data(self, other: CallSynthesisData) -> None:
|
290
|
-
self._synthesis_data = self._synthesis_data.merge(other)
|
291
|
-
|
292
280
|
@pydantic.root_validator()
|
293
281
|
def validate_handles(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
294
282
|
inputs = values.get("inputs", dict())
|
@@ -62,13 +62,8 @@ class HandleValidator(HandleValidationBase):
|
|
62
62
|
elif isinstance(op, WithinApply):
|
63
63
|
self._handle_apply(op.action)
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
self._handle_outputs(op.wiring_inputs)
|
68
|
-
else:
|
69
|
-
self._handle_inputs(op.wiring_inputs)
|
70
|
-
self._handle_outputs(op.wiring_outputs)
|
71
|
-
|
65
|
+
self._handle_inputs(op.wiring_inputs)
|
66
|
+
self._handle_outputs(op.wiring_outputs)
|
72
67
|
self._handle_inouts(op.wiring_inouts)
|
73
68
|
|
74
69
|
def handle_variable_declaration(
|
@@ -37,6 +37,7 @@ IDE_QASM_TASK = f"{TASKS_SUFFIX}/generated_circuit_from_qasm"
|
|
37
37
|
IDE_QASM_FULL_PATH = f"{ANALYZER_PREFIX}{IDE_QASM_TASK}"
|
38
38
|
TASKS_GENERATE_SUFFIX = TASKS_SUFFIX + "/generate"
|
39
39
|
TASKS_VISUALIZE_SUFFIX = TASKS_SUFFIX + "/visualize"
|
40
|
+
TASKS_VISUAL_MODEL_SUFFIX = TASKS_SUFFIX + "/visual_model"
|
40
41
|
TASKS_SOLVE_SUFFIX = "/tasks/solve"
|
41
42
|
MODEL_GENERATE_PREFIX = "/generate_model"
|
42
43
|
CHEMISTRY_GENERATE_MODEL_PATH = MODEL_GENERATE_PREFIX + "/chemistry"
|
@@ -15,7 +15,7 @@ from classiq.interface.generator.functions.qmod_python_interface import QmodPySt
|
|
15
15
|
from classiq.applications.qsvm.qsvm import Data, Labels
|
16
16
|
from classiq.exceptions import ClassiqError
|
17
17
|
|
18
|
-
ExecutionParams = Dict[str, Union[float, int]]
|
18
|
+
ExecutionParams = Dict[str, Union[float, int, List[int], List[float]]]
|
19
19
|
|
20
20
|
_CALL_IN_QFUNC_ERROR = (
|
21
21
|
'Cannot call "{}" in a quantum context. "{}" is a classical execution primitive.'
|
@@ -474,13 +474,6 @@ def exponentiation_with_depth_constraint(
|
|
474
474
|
pass
|
475
475
|
|
476
476
|
|
477
|
-
@qfunc(external=True)
|
478
|
-
def qft_step(
|
479
|
-
target: QArray[QBit],
|
480
|
-
) -> None:
|
481
|
-
pass
|
482
|
-
|
483
|
-
|
484
477
|
@qfunc(external=True)
|
485
478
|
def qft(
|
486
479
|
target: QArray[QBit],
|
@@ -538,7 +531,7 @@ def amplitude_estimation(
|
|
538
531
|
|
539
532
|
@qfunc(external=True)
|
540
533
|
def phase_oracle(
|
541
|
-
predicate: QCallable[QArray[QBit],
|
534
|
+
predicate: QCallable[QArray[QBit], QBit],
|
542
535
|
target: QArray[QBit],
|
543
536
|
) -> None:
|
544
537
|
pass
|
@@ -603,7 +596,7 @@ def qft_no_swap(
|
|
603
596
|
def _check_msb(
|
604
597
|
ref: CInt,
|
605
598
|
x: QArray[QBit],
|
606
|
-
aux:
|
599
|
+
aux: QBit,
|
607
600
|
) -> None:
|
608
601
|
pass
|
609
602
|
|
@@ -612,7 +605,7 @@ def _check_msb(
|
|
612
605
|
def _ctrl_x(
|
613
606
|
ref: CInt,
|
614
607
|
ctrl: QNum,
|
615
|
-
aux:
|
608
|
+
aux: QBit,
|
616
609
|
) -> None:
|
617
610
|
pass
|
618
611
|
|
@@ -630,9 +623,9 @@ def cc_modular_add(
|
|
630
623
|
n: CInt,
|
631
624
|
a: CInt,
|
632
625
|
phi_b: QArray[QBit],
|
633
|
-
c1:
|
634
|
-
c2:
|
635
|
-
aux:
|
626
|
+
c1: QBit,
|
627
|
+
c2: QBit,
|
628
|
+
aux: QBit,
|
636
629
|
) -> None:
|
637
630
|
pass
|
638
631
|
|
@@ -643,8 +636,8 @@ def c_modular_multiply(
|
|
643
636
|
a: CInt,
|
644
637
|
b: QArray[QBit],
|
645
638
|
x: QArray[QBit],
|
646
|
-
ctrl:
|
647
|
-
aux:
|
639
|
+
ctrl: QBit,
|
640
|
+
aux: QBit,
|
648
641
|
) -> None:
|
649
642
|
pass
|
650
643
|
|
@@ -662,8 +655,8 @@ def inplace_c_modular_multiply(
|
|
662
655
|
n: CInt,
|
663
656
|
a: CInt,
|
664
657
|
x: QArray[QBit],
|
665
|
-
ctrl:
|
666
|
-
aux:
|
658
|
+
ctrl: QBit,
|
659
|
+
aux: QBit,
|
667
660
|
) -> None:
|
668
661
|
pass
|
669
662
|
|
@@ -680,13 +673,13 @@ def modular_exp(
|
|
680
673
|
|
681
674
|
@qfunc(external=True)
|
682
675
|
def qsvt_step(
|
683
|
-
|
684
|
-
|
685
|
-
proj_cnot_1: QCallable[QArray[QBit],
|
686
|
-
proj_cnot_2: QCallable[QArray[QBit],
|
676
|
+
phase1: CReal,
|
677
|
+
phase2: CReal,
|
678
|
+
proj_cnot_1: QCallable[QArray[QBit], QBit],
|
679
|
+
proj_cnot_2: QCallable[QArray[QBit], QBit],
|
687
680
|
u: QCallable[QArray[QBit]],
|
688
681
|
qvar: QArray[QBit],
|
689
|
-
aux:
|
682
|
+
aux: QBit,
|
690
683
|
) -> None:
|
691
684
|
pass
|
692
685
|
|
@@ -694,11 +687,11 @@ def qsvt_step(
|
|
694
687
|
@qfunc(external=True)
|
695
688
|
def qsvt(
|
696
689
|
phase_seq: CArray[CReal],
|
697
|
-
proj_cnot_1: QCallable[QArray[QBit],
|
698
|
-
proj_cnot_2: QCallable[QArray[QBit],
|
690
|
+
proj_cnot_1: QCallable[QArray[QBit], QBit],
|
691
|
+
proj_cnot_2: QCallable[QArray[QBit], QBit],
|
699
692
|
u: QCallable[QArray[QBit]],
|
700
693
|
qvar: QArray[QBit],
|
701
|
-
aux:
|
694
|
+
aux: QBit,
|
702
695
|
) -> None:
|
703
696
|
pass
|
704
697
|
|
@@ -706,9 +699,9 @@ def qsvt(
|
|
706
699
|
@qfunc(external=True)
|
707
700
|
def projector_controlled_phase(
|
708
701
|
phase: CReal,
|
709
|
-
proj_cnot: QCallable[QArray[QBit],
|
702
|
+
proj_cnot: QCallable[QArray[QBit], QBit],
|
710
703
|
qvar: QArray[QBit],
|
711
|
-
aux:
|
704
|
+
aux: QBit,
|
712
705
|
) -> None:
|
713
706
|
pass
|
714
707
|
|
@@ -716,10 +709,10 @@ def projector_controlled_phase(
|
|
716
709
|
@qfunc(external=True)
|
717
710
|
def qsvt_inversion(
|
718
711
|
phase_seq: CArray[CReal],
|
719
|
-
block_encoding_cnot: QCallable[QArray[QBit],
|
712
|
+
block_encoding_cnot: QCallable[QArray[QBit], QBit],
|
720
713
|
u: QCallable[QArray[QBit]],
|
721
714
|
qvar: QArray[QBit],
|
722
|
-
aux:
|
715
|
+
aux: QBit,
|
723
716
|
) -> None:
|
724
717
|
pass
|
725
718
|
|
@@ -796,7 +789,7 @@ def full_hea(
|
|
796
789
|
def swap_test(
|
797
790
|
state1: QArray[QBit],
|
798
791
|
state2: QArray[QBit],
|
799
|
-
test: Output[
|
792
|
+
test: Output[QBit],
|
800
793
|
) -> None:
|
801
794
|
pass
|
802
795
|
|
@@ -849,6 +842,59 @@ def switch(
|
|
849
842
|
pass
|
850
843
|
|
851
844
|
|
845
|
+
@qfunc(external=True)
|
846
|
+
def _qct_d_operator(
|
847
|
+
x: QNum,
|
848
|
+
q: QBit,
|
849
|
+
) -> None:
|
850
|
+
pass
|
851
|
+
|
852
|
+
|
853
|
+
@qfunc(external=True)
|
854
|
+
def _qct_pi_operator(
|
855
|
+
x: QArray[QBit],
|
856
|
+
q: QBit,
|
857
|
+
) -> None:
|
858
|
+
pass
|
859
|
+
|
860
|
+
|
861
|
+
@qfunc(external=True)
|
862
|
+
def qct_qst_type1(
|
863
|
+
x: QArray[QBit],
|
864
|
+
) -> None:
|
865
|
+
pass
|
866
|
+
|
867
|
+
|
868
|
+
@qfunc(external=True)
|
869
|
+
def qct_qst_type2(
|
870
|
+
x: QArray[QBit],
|
871
|
+
q: QBit,
|
872
|
+
) -> None:
|
873
|
+
pass
|
874
|
+
|
875
|
+
|
876
|
+
@qfunc(external=True)
|
877
|
+
def qct_type2(
|
878
|
+
x: QArray[QBit],
|
879
|
+
) -> None:
|
880
|
+
pass
|
881
|
+
|
882
|
+
|
883
|
+
@qfunc(external=True)
|
884
|
+
def qst_type2(
|
885
|
+
x: QArray[QBit],
|
886
|
+
) -> None:
|
887
|
+
pass
|
888
|
+
|
889
|
+
|
890
|
+
@qfunc(external=True)
|
891
|
+
def modular_increment(
|
892
|
+
a: CInt,
|
893
|
+
x: QArray[QBit],
|
894
|
+
) -> None:
|
895
|
+
pass
|
896
|
+
|
897
|
+
|
852
898
|
__all__ = [
|
853
899
|
"permute",
|
854
900
|
"apply",
|
@@ -906,7 +952,6 @@ __all__ = [
|
|
906
952
|
"suzuki_trotter",
|
907
953
|
"qdrift",
|
908
954
|
"exponentiation_with_depth_constraint",
|
909
|
-
"qft_step",
|
910
955
|
"qft",
|
911
956
|
"qpe_flexible",
|
912
957
|
"qpe",
|
@@ -947,4 +992,11 @@ __all__ = [
|
|
947
992
|
"inplace_prepare_int",
|
948
993
|
"prepare_int",
|
949
994
|
"switch",
|
995
|
+
"_qct_d_operator",
|
996
|
+
"_qct_pi_operator",
|
997
|
+
"qct_qst_type1",
|
998
|
+
"qct_qst_type2",
|
999
|
+
"qct_type2",
|
1000
|
+
"qst_type2",
|
1001
|
+
"modular_increment",
|
950
1002
|
]
|
@@ -161,7 +161,12 @@ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) ->
|
|
161
161
|
name=REPEAT_OPERATOR_NAME, param_decls={"index": Integer()}
|
162
162
|
),
|
163
163
|
iteration,
|
164
|
+
repeat.__name__,
|
164
165
|
)
|
166
|
+
if not isinstance(iteration_operand, QuantumLambdaFunction):
|
167
|
+
raise ClassiqValueError(
|
168
|
+
"`repeat`'s `iteration` argument must be a lambda function"
|
169
|
+
)
|
165
170
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
166
171
|
Repeat(
|
167
172
|
iter_var=inspect.getfullargspec(iteration).args[0],
|
@@ -251,7 +256,17 @@ def _get_operand_hint(
|
|
251
256
|
|
252
257
|
|
253
258
|
def _operand_to_body(callable_: Union[QCallable, Callable[[], None]]) -> StatementBlock:
|
254
|
-
|
259
|
+
op_name = sys._getframe(1).f_code.co_name
|
260
|
+
if (
|
261
|
+
isinstance(callable_, QCallable)
|
262
|
+
and len(callable_.func_decl.positional_arg_declarations) > 0
|
263
|
+
):
|
264
|
+
raise ClassiqValueError(
|
265
|
+
f"Operand argument {callable_.func_decl.name!r} to {op_name!r} should "
|
266
|
+
f"receive 0 parameters, not "
|
267
|
+
f"{len(callable_.func_decl.positional_arg_declarations)}"
|
268
|
+
)
|
269
|
+
to_operand = prepare_arg(QuantumOperandDeclaration(name=""), callable_, op_name)
|
255
270
|
if isinstance(to_operand, str):
|
256
271
|
return [QuantumFunctionCall(function=to_operand)]
|
257
272
|
elif isinstance(to_operand, QuantumLambdaFunction):
|
@@ -1,9 +1,23 @@
|
|
1
1
|
import dataclasses
|
2
2
|
import inspect
|
3
|
-
from typing import
|
3
|
+
from typing import (
|
4
|
+
Any,
|
5
|
+
Callable,
|
6
|
+
Dict,
|
7
|
+
List,
|
8
|
+
Mapping,
|
9
|
+
Optional,
|
10
|
+
Type,
|
11
|
+
get_args,
|
12
|
+
get_origin,
|
13
|
+
)
|
4
14
|
|
5
15
|
from typing_extensions import _AnnotatedAlias
|
6
16
|
|
17
|
+
from classiq.interface.generator.expressions.enums.ladder_operator import (
|
18
|
+
LadderOperator as LadderOperatorEnum,
|
19
|
+
)
|
20
|
+
from classiq.interface.generator.expressions.enums.pauli import Pauli as PauliEnum
|
7
21
|
from classiq.interface.generator.functions.classical_type import (
|
8
22
|
Bool,
|
9
23
|
ClassicalArray,
|
@@ -11,6 +25,8 @@ from classiq.interface.generator.functions.classical_type import (
|
|
11
25
|
ConcreteClassicalType,
|
12
26
|
CStructBase,
|
13
27
|
Integer,
|
28
|
+
LadderOperator as LadderOperatorType,
|
29
|
+
Pauli as PauliType,
|
14
30
|
Real,
|
15
31
|
Struct,
|
16
32
|
)
|
@@ -33,6 +49,10 @@ from classiq.qmod.quantum_callable import QCallable, QCallableList
|
|
33
49
|
from classiq.qmod.utilities import unmangle_keyword, version_portable_get_args
|
34
50
|
|
35
51
|
OPERAND_ARG_NAME = "arg{i}"
|
52
|
+
ENUM_TYPE_MAPPING: Mapping[type, type] = {
|
53
|
+
PauliEnum: PauliType,
|
54
|
+
LadderOperatorEnum: LadderOperatorType,
|
55
|
+
}
|
36
56
|
|
37
57
|
|
38
58
|
def python_type_to_qmod(
|
@@ -44,6 +64,8 @@ def python_type_to_qmod(
|
|
44
64
|
return Real()
|
45
65
|
elif py_type == bool or py_type is CBool:
|
46
66
|
return Bool()
|
67
|
+
elif py_type in ENUM_TYPE_MAPPING:
|
68
|
+
return ENUM_TYPE_MAPPING[py_type]()
|
47
69
|
elif get_origin(py_type) == list:
|
48
70
|
return ClassicalList(
|
49
71
|
element_type=python_type_to_qmod(get_args(py_type)[0], qmodule=qmodule)
|
@@ -124,9 +146,11 @@ def _extract_positional_args(
|
|
124
146
|
name = unmangle_keyword(name)
|
125
147
|
if (
|
126
148
|
inspect.isclass(py_type)
|
127
|
-
and
|
128
|
-
|
129
|
-
|
149
|
+
and (
|
150
|
+
issubclass(py_type, CParam)
|
151
|
+
or issubclass(py_type, CStructBase)
|
152
|
+
or py_type in ENUM_TYPE_MAPPING
|
153
|
+
)
|
130
154
|
or get_origin(py_type) == CArray
|
131
155
|
):
|
132
156
|
result.append(
|