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.
Files changed (45) hide show
  1. classiq/__init__.py +3 -0
  2. classiq/_internals/api_wrapper.py +29 -4
  3. classiq/applications/chemistry/op_utils.py +31 -1
  4. classiq/applications/chemistry/problems.py +18 -6
  5. classiq/applications/chemistry/ucc.py +2 -2
  6. classiq/evaluators/parameter_types.py +1 -4
  7. classiq/evaluators/qmod_node_evaluators/utils.py +6 -3
  8. classiq/execution/__init__.py +11 -1
  9. classiq/execution/jobs.py +122 -5
  10. classiq/interface/_version.py +1 -1
  11. classiq/interface/exceptions.py +0 -42
  12. classiq/interface/executor/execution_request.py +1 -0
  13. classiq/interface/executor/quantum_code.py +0 -6
  14. classiq/interface/generator/generation_request.py +9 -4
  15. classiq/interface/generator/quantum_program.py +8 -36
  16. classiq/interface/helpers/model_normalizer.py +24 -0
  17. classiq/interface/helpers/text_utils.py +17 -6
  18. classiq/interface/model/invert.py +7 -0
  19. classiq/interface/model/model.py +42 -3
  20. classiq/interface/model/quantum_function_call.py +17 -5
  21. classiq/model_expansions/interpreters/base_interpreter.py +3 -2
  22. classiq/model_expansions/visitors/uncomputation_signature_inference.py +15 -38
  23. classiq/open_library/functions/__init__.py +42 -27
  24. classiq/open_library/functions/bit_operations.py +30 -0
  25. classiq/open_library/functions/modular_arithmetics.py +597 -0
  26. classiq/open_library/functions/qft_space_arithmetics.py +81 -0
  27. classiq/open_library/functions/state_preparation.py +6 -3
  28. classiq/open_library/functions/utility_functions.py +22 -3
  29. classiq/qmod/builtins/functions/exponentiation.py +2 -2
  30. classiq/qmod/builtins/operations.py +29 -4
  31. classiq/qmod/native/pretty_printer.py +15 -4
  32. classiq/qmod/pretty_print/pretty_printer.py +14 -2
  33. classiq/qmod/quantum_callable.py +8 -2
  34. classiq/qmod/quantum_expandable.py +3 -1
  35. classiq/qmod/quantum_function.py +2 -1
  36. classiq/qmod/utilities.py +7 -4
  37. classiq/synthesis_action/__init__.py +20 -0
  38. classiq/synthesis_action/actions.py +106 -0
  39. {classiq-0.100.0.dist-info → classiq-0.102.0.dist-info}/METADATA +1 -1
  40. {classiq-0.100.0.dist-info → classiq-0.102.0.dist-info}/RECORD +42 -40
  41. classiq/interface/executor/register_initialization.py +0 -36
  42. classiq/open_library/functions/modular_exponentiation.py +0 -272
  43. classiq/open_library/functions/qsvt_temp.py +0 -536
  44. {classiq-0.100.0.dist-info → classiq-0.102.0.dist-info}/WHEEL +0 -0
  45. {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
- should_warn: bool = pydantic.Field(default=False)
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=self.data.qubit_mapping.physical_outputs,
110
- registers_initialization=registers_initialization,
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
- def s(items: list | int) -> str:
2
- if isinstance(items, list):
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: list) -> str:
10
+ def are(items: Sized) -> str:
8
11
  return "is" if len(items) == 1 else "are"
9
12
 
10
13
 
11
- def they(items: list) -> str:
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: list) -> str:
26
+ def conj(items: Sized) -> str:
16
27
  return "s" if len(items) == 1 else ""
17
28
 
18
29
 
19
- def readable_list(items: list, quote: bool = False) -> str:
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"])
@@ -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
- debug_info: DebugInfoCollection = pydantic.Field(
100
- default_factory=DebugInfoCollection
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
- (idx, port, handle)
226
- for idx, (port, handle) in enumerate(
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
- param
231
- for param in self.positional_args
232
- if isinstance(param, HandleBinding)
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
- return Model(
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
- warnings.warn(
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
- warnings.warn(
261
- _non_permutation_usage(func_def.name, source_ref),
262
- ClassiqDeprecationWarning,
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
- warnings.warn(
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}.{source_ref_str}\n"
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.\n"
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
- f"Non-permutation operation used in a permutation function {function_name.split('_' + EXPANDED_KEYWORD)[0]!r}.{source_ref_str}\n"
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.\n"
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 .modular_exponentiation import *
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 gqsp
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
- inplace_c_modular_multiply,
52
- modular_exp,
53
- qsvt_step_old,
54
- qsvt_step_new,
55
- qsvt_old,
56
- qsvt_new,
57
- projector_controlled_double_phase_old,
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
- "modular_increment",
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)