classiq 0.100.0__py3-none-any.whl → 0.102.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/__init__.py +3 -0
- classiq/_internals/api_wrapper.py +29 -4
- classiq/applications/chemistry/op_utils.py +31 -1
- classiq/applications/chemistry/problems.py +18 -6
- classiq/applications/chemistry/ucc.py +2 -2
- classiq/evaluators/parameter_types.py +1 -4
- classiq/evaluators/qmod_node_evaluators/utils.py +6 -3
- classiq/execution/__init__.py +11 -1
- classiq/execution/jobs.py +122 -5
- classiq/interface/_version.py +1 -1
- classiq/interface/exceptions.py +0 -42
- classiq/interface/executor/execution_request.py +1 -0
- classiq/interface/executor/quantum_code.py +0 -6
- classiq/interface/generator/generation_request.py +9 -4
- classiq/interface/generator/quantum_program.py +8 -36
- classiq/interface/helpers/model_normalizer.py +24 -0
- classiq/interface/helpers/text_utils.py +17 -6
- classiq/interface/model/invert.py +7 -0
- classiq/interface/model/model.py +42 -3
- classiq/interface/model/quantum_function_call.py +17 -5
- classiq/model_expansions/interpreters/base_interpreter.py +3 -2
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +15 -38
- classiq/open_library/functions/__init__.py +42 -27
- classiq/open_library/functions/bit_operations.py +30 -0
- classiq/open_library/functions/modular_arithmetics.py +597 -0
- classiq/open_library/functions/qft_space_arithmetics.py +81 -0
- classiq/open_library/functions/state_preparation.py +6 -3
- classiq/open_library/functions/utility_functions.py +22 -3
- classiq/qmod/builtins/functions/exponentiation.py +2 -2
- classiq/qmod/builtins/operations.py +29 -4
- classiq/qmod/native/pretty_printer.py +15 -4
- classiq/qmod/pretty_print/pretty_printer.py +14 -2
- classiq/qmod/quantum_callable.py +8 -2
- classiq/qmod/quantum_expandable.py +3 -1
- classiq/qmod/quantum_function.py +2 -1
- classiq/qmod/utilities.py +7 -4
- classiq/synthesis_action/__init__.py +20 -0
- classiq/synthesis_action/actions.py +106 -0
- {classiq-0.100.0.dist-info → classiq-0.102.0.dist-info}/METADATA +1 -1
- {classiq-0.100.0.dist-info → classiq-0.102.0.dist-info}/RECORD +42 -40
- classiq/interface/executor/register_initialization.py +0 -36
- classiq/open_library/functions/modular_exponentiation.py +0 -272
- classiq/open_library/functions/qsvt_temp.py +0 -536
- {classiq-0.100.0.dist-info → classiq-0.102.0.dist-info}/WHEEL +0 -0
- {classiq-0.100.0.dist-info → classiq-0.102.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -10,12 +10,10 @@ from classiq.interface.compression_utils import decompress
|
|
|
10
10
|
from classiq.interface.exceptions import (
|
|
11
11
|
ClassiqDeprecationWarning,
|
|
12
12
|
ClassiqMissingOutputFormatError,
|
|
13
|
-
ClassiqStateInitializationError,
|
|
14
13
|
)
|
|
15
14
|
from classiq.interface.execution.primitives import PrimitivesInput
|
|
16
15
|
from classiq.interface.executor import quantum_code
|
|
17
16
|
from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
|
|
18
|
-
from classiq.interface.executor.register_initialization import RegisterInitialization
|
|
19
17
|
from classiq.interface.generator.circuit_code.circuit_code import CircuitCodeInterface
|
|
20
18
|
from classiq.interface.generator.circuit_code.types_and_constants import (
|
|
21
19
|
INSTRUCTION_SET_TO_FORMAT,
|
|
@@ -29,9 +27,9 @@ from classiq.interface.generator.hardware.hardware_data import SynthesisHardware
|
|
|
29
27
|
from classiq.interface.generator.model.model import ExecutionModel
|
|
30
28
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
|
31
29
|
from classiq.interface.ide.visual_model import CircuitMetrics
|
|
30
|
+
from classiq.interface.model.model import Model
|
|
32
31
|
|
|
33
32
|
RegisterName: TypeAlias = str
|
|
34
|
-
InitialConditions: TypeAlias = dict[RegisterName, int]
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
class TranspiledCircuitData(CircuitCodeInterface):
|
|
@@ -56,7 +54,6 @@ def _get_formatted_utc_current_time() -> str:
|
|
|
56
54
|
|
|
57
55
|
class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
58
56
|
hardware_data: SynthesisHardwareData
|
|
59
|
-
initial_values: InitialConditions | None = pydantic.Field(default=None)
|
|
60
57
|
data: GeneratedCircuitData
|
|
61
58
|
model: ExecutionModel
|
|
62
59
|
transpiled_circuit: TranspiledCircuitData | None = pydantic.Field(default=None)
|
|
@@ -65,7 +62,7 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
|
65
62
|
program_id: str = pydantic.Field(default_factory=get_uuid_as_str)
|
|
66
63
|
execution_primitives_input: PrimitivesInput | None = pydantic.Field(default=None)
|
|
67
64
|
synthesis_warnings: list[str] | None = pydantic.Field(default=None)
|
|
68
|
-
|
|
65
|
+
compiled_qmod: Model | None = pydantic.Field(default=None)
|
|
69
66
|
|
|
70
67
|
def __str__(self) -> str:
|
|
71
68
|
return self.model_dump_json(indent=2)
|
|
@@ -85,10 +82,8 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
|
85
82
|
|
|
86
83
|
def to_program(
|
|
87
84
|
self,
|
|
88
|
-
initial_values: InitialConditions | None = None,
|
|
89
85
|
instruction_set: QuantumInstructionSet | None = None,
|
|
90
86
|
) -> quantum_code.QuantumCode:
|
|
91
|
-
initial_values = initial_values or self.initial_values
|
|
92
87
|
if instruction_set is not None:
|
|
93
88
|
code, syntax = (
|
|
94
89
|
self.program_circuit.get_code(instruction_set),
|
|
@@ -97,40 +92,17 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
|
97
92
|
else:
|
|
98
93
|
code, syntax = self._default_program_code()
|
|
99
94
|
|
|
100
|
-
if initial_values is not None:
|
|
101
|
-
registers_initialization = self.get_registers_initialization(
|
|
102
|
-
initial_values=initial_values
|
|
103
|
-
)
|
|
104
|
-
else:
|
|
105
|
-
registers_initialization = None
|
|
106
95
|
return quantum_code.QuantumCode(
|
|
107
96
|
code=code,
|
|
108
97
|
syntax=syntax,
|
|
109
|
-
output_qubits_map=
|
|
110
|
-
|
|
98
|
+
output_qubits_map=(
|
|
99
|
+
self.data.qubit_mapping.physical_outputs
|
|
100
|
+
if self._can_use_transpiled_code
|
|
101
|
+
else self.data.qubit_mapping.logical_outputs
|
|
102
|
+
),
|
|
111
103
|
synthesis_execution_data=self.data.execution_data,
|
|
112
104
|
)
|
|
113
105
|
|
|
114
|
-
def _get_initialization_qubits(self, name: str) -> tuple[int, ...]:
|
|
115
|
-
qubits = self.data.qubit_mapping.logical_inputs.get(name)
|
|
116
|
-
if qubits is None:
|
|
117
|
-
raise ClassiqStateInitializationError(
|
|
118
|
-
f"Cannot initialize register {name}, it does not appear in circuit inputs"
|
|
119
|
-
)
|
|
120
|
-
return qubits
|
|
121
|
-
|
|
122
|
-
def get_registers_initialization(
|
|
123
|
-
self, initial_values: InitialConditions
|
|
124
|
-
) -> dict[RegisterName, RegisterInitialization]:
|
|
125
|
-
return {
|
|
126
|
-
name: RegisterInitialization(
|
|
127
|
-
name=name,
|
|
128
|
-
qubits=list(self._get_initialization_qubits(name)),
|
|
129
|
-
initial_condition=init_value,
|
|
130
|
-
)
|
|
131
|
-
for name, init_value in initial_values.items()
|
|
132
|
-
}
|
|
133
|
-
|
|
134
106
|
def save_results(self, filename: str | Path | None = None) -> None:
|
|
135
107
|
"""
|
|
136
108
|
Saves quantum program results as json into a file.
|
|
@@ -148,7 +120,7 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
|
148
120
|
|
|
149
121
|
@property
|
|
150
122
|
def _can_use_transpiled_code(self) -> bool:
|
|
151
|
-
return (
|
|
123
|
+
return self.transpiled_circuit is not None and (
|
|
152
124
|
self.data.execution_data is None
|
|
153
125
|
or not self.data.execution_data.function_execution
|
|
154
126
|
)
|
|
@@ -7,10 +7,16 @@ from classiq.interface.generator.functions.classical_type import ClassicalType
|
|
|
7
7
|
from classiq.interface.generator.functions.type_modifier import TypeModifier
|
|
8
8
|
from classiq.interface.generator.visitor import Transformer, Visitor
|
|
9
9
|
from classiq.interface.model.model import Model
|
|
10
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
|
10
11
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
|
12
|
+
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class ModelNormalizer(Visitor):
|
|
16
|
+
def __init__(self, normalize_names: bool = False) -> None:
|
|
17
|
+
self._normalize_names = normalize_names
|
|
18
|
+
self._funcs_renames: dict[str, str] = {}
|
|
19
|
+
|
|
14
20
|
def visit(self, node: Any) -> None:
|
|
15
21
|
if isinstance(node, ASTNode):
|
|
16
22
|
node.model_config["frozen"] = False
|
|
@@ -23,8 +29,26 @@ class ModelNormalizer(Visitor):
|
|
|
23
29
|
def visit_Model(self, model: Model) -> None:
|
|
24
30
|
model.debug_info = DebugInfoCollection()
|
|
25
31
|
model.functions.sort(key=lambda x: x.name)
|
|
32
|
+
self._funcs_renames = {
|
|
33
|
+
func.name: f"___func_{index}" for index, func in enumerate(model.functions)
|
|
34
|
+
}
|
|
26
35
|
self.generic_visit(model)
|
|
27
36
|
|
|
37
|
+
def visit_NativeFunctionDefinition(self, func: NativeFunctionDefinition) -> None:
|
|
38
|
+
if self._normalize_names:
|
|
39
|
+
func.name = self._funcs_renames[func.name]
|
|
40
|
+
self.generic_visit(func)
|
|
41
|
+
|
|
42
|
+
def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
|
|
43
|
+
if self._normalize_names:
|
|
44
|
+
if isinstance(call.function, str):
|
|
45
|
+
if call.function in self._funcs_renames:
|
|
46
|
+
call.function = self._funcs_renames[call.function]
|
|
47
|
+
else:
|
|
48
|
+
if call.function.name in self._funcs_renames:
|
|
49
|
+
call.function.name = self._funcs_renames[call.function.name]
|
|
50
|
+
self.generic_visit(call)
|
|
51
|
+
|
|
28
52
|
def visit_AnonPortDeclaration(self, decl: AnonPortDeclaration) -> None:
|
|
29
53
|
decl.type_modifier = TypeModifier.Mutable
|
|
30
54
|
|
|
@@ -1,22 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
from collections.abc import Sequence, Sized
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def s(items: Sized | int) -> str:
|
|
5
|
+
if isinstance(items, Sized):
|
|
3
6
|
items = len(items)
|
|
4
7
|
return "" if items == 1 else "s"
|
|
5
8
|
|
|
6
9
|
|
|
7
|
-
def are(items:
|
|
10
|
+
def are(items: Sized) -> str:
|
|
8
11
|
return "is" if len(items) == 1 else "are"
|
|
9
12
|
|
|
10
13
|
|
|
11
|
-
def
|
|
14
|
+
def were(items: Sized) -> str:
|
|
15
|
+
return "was" if len(items) == 1 else "were"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def an(items: Sized) -> str:
|
|
19
|
+
return "an " if len(items) == 1 else ""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def they(items: Sized) -> str:
|
|
12
23
|
return "it" if len(items) == 1 else "they"
|
|
13
24
|
|
|
14
25
|
|
|
15
|
-
def conj(items:
|
|
26
|
+
def conj(items: Sized) -> str:
|
|
16
27
|
return "s" if len(items) == 1 else ""
|
|
17
28
|
|
|
18
29
|
|
|
19
|
-
def readable_list(items:
|
|
30
|
+
def readable_list(items: Sequence, quote: bool = False) -> str:
|
|
20
31
|
if quote:
|
|
21
32
|
items = [repr(str(item)) for item in items]
|
|
22
33
|
if len(items) == 1:
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, Literal
|
|
2
2
|
|
|
3
3
|
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
|
4
|
+
from classiq.interface.enum_utils import StrEnum
|
|
4
5
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
|
5
6
|
|
|
6
7
|
if TYPE_CHECKING:
|
|
7
8
|
from classiq.interface.model.statement_block import StatementBlock
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
class BlockKind(StrEnum):
|
|
12
|
+
SingleCall = "single_call"
|
|
13
|
+
Compound = "compound"
|
|
14
|
+
|
|
15
|
+
|
|
10
16
|
class Invert(QuantumOperation):
|
|
11
17
|
kind: Literal["Invert"]
|
|
12
18
|
|
|
13
19
|
body: "StatementBlock"
|
|
20
|
+
block_kind: BlockKind = BlockKind.Compound
|
|
14
21
|
|
|
15
22
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
|
16
23
|
return reset_lists(self, ["body"])
|
classiq/interface/model/model.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import Annotated, Any, Literal, NewType
|
|
|
5
5
|
import pydantic
|
|
6
6
|
|
|
7
7
|
from classiq.interface.ast_node import ASTNode
|
|
8
|
+
from classiq.interface.compression_utils import compress_pydantic, decompress
|
|
8
9
|
from classiq.interface.debug_info.debug_info import DebugInfoCollection
|
|
9
10
|
from classiq.interface.exceptions import ClassiqValueError
|
|
10
11
|
from classiq.interface.executor.execution_preferences import ExecutionPreferences
|
|
@@ -96,9 +97,9 @@ class Model(VersionedModel, ASTNode):
|
|
|
96
97
|
)
|
|
97
98
|
preferences: Preferences = pydantic.Field(default_factory=Preferences)
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
_debug_info: DebugInfoCollection | None = pydantic.PrivateAttr(default=None)
|
|
101
|
+
compressed_debug_info: bytes | None = pydantic.Field(default=None)
|
|
102
|
+
|
|
102
103
|
functions_compilation_metadata: defaultdict[
|
|
103
104
|
str,
|
|
104
105
|
Annotated[
|
|
@@ -198,3 +199,41 @@ class Model(VersionedModel, ASTNode):
|
|
|
198
199
|
return model.model_dump(
|
|
199
200
|
exclude={"constraints", "execution_preferences", "preferences"},
|
|
200
201
|
)
|
|
202
|
+
|
|
203
|
+
# TODO (CLS-4966): remove
|
|
204
|
+
@pydantic.model_validator(mode="wrap")
|
|
205
|
+
@classmethod
|
|
206
|
+
def get_deprecated_debug_info(
|
|
207
|
+
cls, data: Any, handler: pydantic.ModelWrapValidatorHandler
|
|
208
|
+
) -> "Model":
|
|
209
|
+
model = handler(data)
|
|
210
|
+
if isinstance(data, dict) and "debug_info" in data:
|
|
211
|
+
model._debug_info = DebugInfoCollection.model_validate(data["debug_info"])
|
|
212
|
+
return model
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def debug_info(self) -> DebugInfoCollection:
|
|
216
|
+
if self._debug_info is None:
|
|
217
|
+
if self.compressed_debug_info is None:
|
|
218
|
+
self._debug_info = DebugInfoCollection()
|
|
219
|
+
else:
|
|
220
|
+
self._debug_info = DebugInfoCollection.model_validate(
|
|
221
|
+
decompress(self.compressed_debug_info)
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
return self._debug_info
|
|
225
|
+
|
|
226
|
+
@debug_info.setter
|
|
227
|
+
def debug_info(self, value: DebugInfoCollection) -> None:
|
|
228
|
+
self._debug_info = value
|
|
229
|
+
self.compressed_debug_info = None
|
|
230
|
+
|
|
231
|
+
def clear_debug_info(self) -> None:
|
|
232
|
+
self._debug_info = None
|
|
233
|
+
self.compressed_debug_info = None
|
|
234
|
+
|
|
235
|
+
def compress_debug_info(self) -> None:
|
|
236
|
+
if self._debug_info is None:
|
|
237
|
+
self.compressed_debug_info = None
|
|
238
|
+
else:
|
|
239
|
+
self.compressed_debug_info = compress_pydantic(self._debug_info)
|
|
@@ -29,6 +29,13 @@ from classiq.interface.model.quantum_lambda_function import (
|
|
|
29
29
|
)
|
|
30
30
|
from classiq.interface.model.quantum_statement import HandleMetadata, QuantumOperation
|
|
31
31
|
|
|
32
|
+
|
|
33
|
+
def _split_concatenation(var: HandleBinding | HandlesList) -> list[HandleBinding]:
|
|
34
|
+
if isinstance(var, HandleBinding):
|
|
35
|
+
return [var]
|
|
36
|
+
return list(chain.from_iterable(_split_concatenation(item) for item in var.handles))
|
|
37
|
+
|
|
38
|
+
|
|
32
39
|
ArgValue = Union[
|
|
33
40
|
Expression,
|
|
34
41
|
QuantumOperand,
|
|
@@ -221,18 +228,23 @@ class QuantumFunctionCall(QuantumOperation):
|
|
|
221
228
|
def _get_handles_with_declarations(
|
|
222
229
|
self,
|
|
223
230
|
) -> Iterable[tuple[int, AnonPortDeclaration, HandleBinding]]:
|
|
231
|
+
"""
|
|
232
|
+
Get variable arguments attached to their position and parameter declaration.
|
|
233
|
+
Splits concatenations into variables.
|
|
234
|
+
"""
|
|
224
235
|
return [
|
|
225
|
-
(
|
|
226
|
-
for
|
|
236
|
+
(positional_idx, port, var)
|
|
237
|
+
for positional_idx, (port, var_or_concatenation) in enumerate(
|
|
227
238
|
zip(
|
|
228
239
|
(port_decl for port_decl in self.func_decl.port_declarations),
|
|
229
240
|
(
|
|
230
|
-
|
|
231
|
-
for
|
|
232
|
-
if isinstance(
|
|
241
|
+
arg
|
|
242
|
+
for arg in self.positional_args
|
|
243
|
+
if isinstance(arg, (HandleBinding, HandlesList))
|
|
233
244
|
),
|
|
234
245
|
)
|
|
235
246
|
)
|
|
247
|
+
for var in _split_concatenation(var_or_concatenation)
|
|
236
248
|
]
|
|
237
249
|
|
|
238
250
|
def _get_readable_location(
|
|
@@ -159,7 +159,7 @@ class BaseInterpreter:
|
|
|
159
159
|
finally:
|
|
160
160
|
self._error_manager.report_errors(ClassiqExpansionError)
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
model = Model(
|
|
163
163
|
constraints=self._model.constraints,
|
|
164
164
|
preferences=self._model.preferences,
|
|
165
165
|
classical_execution_code=self._model.classical_execution_code,
|
|
@@ -181,9 +181,10 @@ class BaseInterpreter:
|
|
|
181
181
|
if name not in BUILTIN_STRUCT_DECLARATIONS
|
|
182
182
|
],
|
|
183
183
|
qstructs=list(QMODULE.qstruct_decls.values()),
|
|
184
|
-
debug_info=self._model.debug_info,
|
|
185
184
|
functions_compilation_metadata=self._expanded_functions_compilation_metadata,
|
|
186
185
|
)
|
|
186
|
+
model.debug_info = self._model.debug_info
|
|
187
|
+
return model
|
|
187
188
|
|
|
188
189
|
def process_exception(self, e: Exception) -> None:
|
|
189
190
|
if not isinstance(e, (ClassiqError, ValidationError)):
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import warnings
|
|
2
1
|
from collections import defaultdict
|
|
3
2
|
from collections.abc import Iterator
|
|
4
3
|
from contextlib import contextmanager
|
|
@@ -6,10 +5,8 @@ from typing import NamedTuple
|
|
|
6
5
|
|
|
7
6
|
from classiq.interface.ast_node import ASTNode
|
|
8
7
|
from classiq.interface.exceptions import (
|
|
9
|
-
ClassiqDeprecationWarning,
|
|
10
8
|
ClassiqInternalExpansionError,
|
|
11
9
|
)
|
|
12
|
-
from classiq.interface.generator.compiler_keywords import EXPANDED_KEYWORD
|
|
13
10
|
from classiq.interface.generator.functions.port_declaration import (
|
|
14
11
|
PortDeclarationDirection,
|
|
15
12
|
)
|
|
@@ -35,6 +32,8 @@ from classiq.interface.model.skip_control import SkipControl
|
|
|
35
32
|
from classiq.interface.model.within_apply_operation import WithinApply
|
|
36
33
|
from classiq.interface.source_reference import SourceReference
|
|
37
34
|
|
|
35
|
+
from classiq.qmod.semantics.error_manager import ErrorManager
|
|
36
|
+
|
|
38
37
|
|
|
39
38
|
class _BoundVars(NamedTuple):
|
|
40
39
|
in_identifiers: list[str]
|
|
@@ -243,11 +242,7 @@ def infer_and_validate_uncomputation_signature(
|
|
|
243
242
|
PortDeclarationDirection.Input,
|
|
244
243
|
PortDeclarationDirection.Output,
|
|
245
244
|
):
|
|
246
|
-
|
|
247
|
-
_input_output_const(port.name, port.direction, func_def.name),
|
|
248
|
-
ClassiqDeprecationWarning,
|
|
249
|
-
stacklevel=1,
|
|
250
|
-
)
|
|
245
|
+
ErrorManager().add_error(_input_output_const(port.name, port.direction))
|
|
251
246
|
|
|
252
247
|
if disable_perm_check and (disable_const_checks is True) and not tighten_signature:
|
|
253
248
|
return
|
|
@@ -257,10 +252,9 @@ def infer_and_validate_uncomputation_signature(
|
|
|
257
252
|
|
|
258
253
|
if not disable_perm_check and func_def.permutation and not visitor.is_permutation():
|
|
259
254
|
for source_ref in visitor.non_permutation_reasons():
|
|
260
|
-
|
|
261
|
-
_non_permutation_usage(
|
|
262
|
-
|
|
263
|
-
stacklevel=1,
|
|
255
|
+
ErrorManager().add_error(
|
|
256
|
+
_non_permutation_usage(),
|
|
257
|
+
source_ref=source_ref,
|
|
264
258
|
)
|
|
265
259
|
|
|
266
260
|
if tighten_signature and not func_def.permutation and visitor.is_permutation():
|
|
@@ -276,10 +270,8 @@ def infer_and_validate_uncomputation_signature(
|
|
|
276
270
|
and not visitor.is_const(port.name)
|
|
277
271
|
):
|
|
278
272
|
for source_ref in visitor.non_const_reasons(port.name):
|
|
279
|
-
|
|
280
|
-
_non_const_usage(port.name, source_ref
|
|
281
|
-
ClassiqDeprecationWarning,
|
|
282
|
-
stacklevel=1,
|
|
273
|
+
ErrorManager().add_error(
|
|
274
|
+
_non_const_usage(port.name), source_ref=source_ref
|
|
283
275
|
)
|
|
284
276
|
|
|
285
277
|
if (
|
|
@@ -293,36 +285,21 @@ def infer_and_validate_uncomputation_signature(
|
|
|
293
285
|
def _input_output_const(
|
|
294
286
|
port_name: str,
|
|
295
287
|
direction: PortDeclarationDirection,
|
|
296
|
-
function_name: str,
|
|
297
288
|
) -> str:
|
|
298
|
-
return (
|
|
299
|
-
f"{direction.capitalize()} parameters cannot be defined as constants"
|
|
300
|
-
f" (parameter {port_name!r} in function {function_name.split('_' + EXPANDED_KEYWORD)[0]!r}).\n"
|
|
301
|
-
"The deprecation warning will be elevated to an error starting 2025-12-03, at the earliest."
|
|
302
|
-
)
|
|
289
|
+
return f"{direction.capitalize()} parameter {port_name!r} cannot be defined as constant."
|
|
303
290
|
|
|
304
291
|
|
|
305
|
-
def _non_const_usage(
|
|
306
|
-
port_name: str,
|
|
307
|
-
source_ref: SourceReference | None = None,
|
|
308
|
-
) -> str:
|
|
309
|
-
source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
|
|
292
|
+
def _non_const_usage(port_name: str) -> str:
|
|
310
293
|
return (
|
|
311
|
-
f"Non-constant usage of a constant parameter {port_name!r}
|
|
294
|
+
f"Non-constant usage of a constant parameter {port_name!r}.\n"
|
|
312
295
|
"Tip: if the commulative use of the parameter in the function is constant, "
|
|
313
|
-
"use the `disable_const_checks` flag to instruct the compiler to disregard individual operations
|
|
314
|
-
"The deprecation warning will be elevated to an error starting 2025-12-03, at the earliest."
|
|
296
|
+
"use the `disable_const_checks` flag to instruct the compiler to disregard individual operations."
|
|
315
297
|
)
|
|
316
298
|
|
|
317
299
|
|
|
318
|
-
def _non_permutation_usage(
|
|
319
|
-
function_name: str,
|
|
320
|
-
source_ref: SourceReference | None = None,
|
|
321
|
-
) -> str:
|
|
322
|
-
source_ref_str = f"\n\tat {source_ref}" if source_ref else ""
|
|
300
|
+
def _non_permutation_usage() -> str:
|
|
323
301
|
return (
|
|
324
|
-
|
|
302
|
+
"Non-permutation operation used in a permutation function.\n"
|
|
325
303
|
"Tip: if the commulative effect of the function is a permutation, "
|
|
326
|
-
"use the `disable_perm_check` flag to instruct the compiler to disregard individual operations
|
|
327
|
-
"The deprecation warning will be elevated to an error starting 2025-12-03, at the earliest."
|
|
304
|
+
"use the `disable_perm_check` flag to instruct the compiler to disregard individual operations."
|
|
328
305
|
)
|
|
@@ -15,13 +15,13 @@ from .hea import *
|
|
|
15
15
|
from .lcu import *
|
|
16
16
|
from .linear_pauli_rotation import *
|
|
17
17
|
from .linear_pauli_rotation import _single_pauli
|
|
18
|
-
from .
|
|
19
|
-
from .modular_exponentiation import _check_msb
|
|
18
|
+
from .modular_arithmetics import *
|
|
20
19
|
from .qaoa_penalty import *
|
|
21
20
|
from .qft_functions import *
|
|
21
|
+
from .qft_space_arithmetics import *
|
|
22
|
+
from .qft_space_arithmetics import _check_msb
|
|
22
23
|
from .qpe import *
|
|
23
|
-
from .qsvt import
|
|
24
|
-
from .qsvt_temp import * # change to .qsvt after deprecation
|
|
24
|
+
from .qsvt import * # change to .qsvt after deprecation
|
|
25
25
|
from .state_preparation import *
|
|
26
26
|
from .state_preparation import _prepare_uniform_trimmed_state_step
|
|
27
27
|
from .swap_test import *
|
|
@@ -31,6 +31,7 @@ from .variational import *
|
|
|
31
31
|
OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
|
|
32
32
|
qpe_flexible,
|
|
33
33
|
qpe,
|
|
34
|
+
_check_msb,
|
|
34
35
|
_single_pauli,
|
|
35
36
|
linear_pauli_rotations,
|
|
36
37
|
amplitude_estimation,
|
|
@@ -45,25 +46,14 @@ OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
|
|
|
45
46
|
apply_to_all,
|
|
46
47
|
qft_no_swap,
|
|
47
48
|
qft_space_add_const,
|
|
48
|
-
cc_modular_add,
|
|
49
|
-
c_modular_multiply,
|
|
50
49
|
multiswap,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
projector_controlled_double_phase_new,
|
|
59
|
-
projector_controlled_phase_old,
|
|
60
|
-
projector_controlled_phase_new,
|
|
61
|
-
qsvt_inversion_old,
|
|
62
|
-
qsvt_inversion_new,
|
|
63
|
-
qsvt_lcu_old,
|
|
64
|
-
qsvt_lcu_new,
|
|
65
|
-
qsvt_lcu_step_old,
|
|
66
|
-
qsvt_lcu_step_new,
|
|
50
|
+
qsvt_step,
|
|
51
|
+
qsvt,
|
|
52
|
+
projector_controlled_double_phase,
|
|
53
|
+
projector_controlled_phase,
|
|
54
|
+
qsvt_inversion,
|
|
55
|
+
qsvt_lcu,
|
|
56
|
+
qsvt_lcu_step,
|
|
67
57
|
gqsp,
|
|
68
58
|
qaoa_mixer_layer,
|
|
69
59
|
qaoa_cost_layer,
|
|
@@ -89,7 +79,6 @@ OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
|
|
|
89
79
|
_prepare_uniform_trimmed_state_step,
|
|
90
80
|
_qct_d_operator,
|
|
91
81
|
_qct_pi_operator,
|
|
92
|
-
_check_msb,
|
|
93
82
|
encode_in_angle,
|
|
94
83
|
encode_on_bloch,
|
|
95
84
|
_cond_phase_flip,
|
|
@@ -99,6 +88,22 @@ OPEN_LIBRARY_FUNCTIONS: list[BaseQFunc] = [
|
|
|
99
88
|
one_hot_to_unary,
|
|
100
89
|
inplace_one_hot_to_unary,
|
|
101
90
|
unary_to_one_hot,
|
|
91
|
+
modular_negate_inplace,
|
|
92
|
+
modular_subtract_inplace,
|
|
93
|
+
modular_double_inplace,
|
|
94
|
+
modular_add_constant_inplace,
|
|
95
|
+
modular_add_inplace,
|
|
96
|
+
modular_multiply,
|
|
97
|
+
modular_square,
|
|
98
|
+
modular_multiply_constant,
|
|
99
|
+
modular_multiply_constant_inplace,
|
|
100
|
+
modular_to_montgomery_inplace,
|
|
101
|
+
modular_montgomery_to_standard_inplace,
|
|
102
|
+
modular_inverse_inplace,
|
|
103
|
+
kaliski_iteration,
|
|
104
|
+
modular_rsub_inplace,
|
|
105
|
+
modular_exp, # TODO: deprecate when ready
|
|
106
|
+
modular_exponentiate,
|
|
102
107
|
]
|
|
103
108
|
|
|
104
109
|
__all__ = [
|
|
@@ -109,8 +114,6 @@ __all__ = [
|
|
|
109
114
|
"assign_amplitude_table",
|
|
110
115
|
"binary_to_one_hot",
|
|
111
116
|
"binary_to_unary",
|
|
112
|
-
"c_modular_multiply",
|
|
113
|
-
"cc_modular_add",
|
|
114
117
|
"encode_in_angle",
|
|
115
118
|
"encode_on_bloch",
|
|
116
119
|
"exact_amplitude_amplification",
|
|
@@ -121,19 +124,31 @@ __all__ = [
|
|
|
121
124
|
"grover_search",
|
|
122
125
|
"hadamard_transform",
|
|
123
126
|
"inplace_binary_to_one_hot",
|
|
124
|
-
"inplace_c_modular_multiply",
|
|
125
127
|
"inplace_modular_multiply",
|
|
126
128
|
"inplace_one_hot_to_unary",
|
|
127
129
|
"inplace_prepare_complex_amplitudes",
|
|
128
130
|
"inplace_prepare_int",
|
|
129
131
|
"inplace_prepare_sparse_amplitudes",
|
|
132
|
+
"kaliski_iteration",
|
|
130
133
|
"lcu",
|
|
131
134
|
"lcu_pauli",
|
|
132
135
|
"linear_pauli_rotations",
|
|
136
|
+
"modular_add_constant_inplace",
|
|
137
|
+
"modular_add_inplace",
|
|
133
138
|
"modular_add_qft_space",
|
|
139
|
+
"modular_double_inplace",
|
|
134
140
|
"modular_exp",
|
|
135
|
-
"
|
|
141
|
+
"modular_exponentiate",
|
|
142
|
+
"modular_inverse_inplace",
|
|
143
|
+
"modular_montgomery_to_standard_inplace",
|
|
136
144
|
"modular_multiply",
|
|
145
|
+
"modular_multiply_constant",
|
|
146
|
+
"modular_multiply_constant_inplace",
|
|
147
|
+
"modular_negate_inplace",
|
|
148
|
+
"modular_rsub_inplace",
|
|
149
|
+
"modular_square",
|
|
150
|
+
"modular_subtract_inplace",
|
|
151
|
+
"modular_to_montgomery_inplace",
|
|
137
152
|
"multiswap",
|
|
138
153
|
"one_hot_to_binary",
|
|
139
154
|
"one_hot_to_unary",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from classiq.open_library.functions.utility_functions import apply_to_all
|
|
2
|
+
from classiq.qmod.builtins.functions.standard_gates import SWAP, X
|
|
3
|
+
from classiq.qmod.builtins.operations import invert, repeat
|
|
4
|
+
from classiq.qmod.qfunc import qperm
|
|
5
|
+
from classiq.qmod.qmod_variable import QArray, QBit
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@qperm
|
|
9
|
+
def cyclic_shift_left(reg: QArray[QBit]) -> None:
|
|
10
|
+
"""
|
|
11
|
+
Performs a left shift on the quantum register array `reg` using SWAP gates.
|
|
12
|
+
"""
|
|
13
|
+
n = reg.size
|
|
14
|
+
repeat(n - 1, lambda i: SWAP(reg[n - i - 1], reg[n - i - 2]))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@qperm
|
|
18
|
+
def cyclic_shift_right(reg: QArray[QBit]) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Performs a right shift on the quantum register array `reg` by inverting cyclic_shift_left.
|
|
21
|
+
"""
|
|
22
|
+
invert(lambda: cyclic_shift_left(reg))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@qperm
|
|
26
|
+
def bitwise_negate(x: QArray[QBit]) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Negates each bit of the input x.
|
|
29
|
+
"""
|
|
30
|
+
apply_to_all(X, x)
|