classiq 0.94.1__py3-none-any.whl → 0.95.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.

Potentially problematic release.


This version of classiq might be problematic. Click here for more details.

Files changed (56) hide show
  1. classiq/_internals/authentication/auth0.py +32 -3
  2. classiq/_internals/authentication/authorization_code.py +9 -0
  3. classiq/_internals/authentication/authorization_flow.py +41 -0
  4. classiq/_internals/authentication/device.py +31 -50
  5. classiq/_internals/authentication/hybrid_flow.py +19 -0
  6. classiq/_internals/authentication/token_manager.py +5 -4
  7. classiq/applications/__init__.py +2 -2
  8. classiq/applications/qsp/qsp.py +6 -5
  9. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +10 -0
  10. classiq/interface/_version.py +1 -1
  11. classiq/interface/backend/backend_preferences.py +11 -6
  12. classiq/interface/exceptions.py +0 -4
  13. classiq/interface/generator/application_apis/__init__.py +0 -1
  14. classiq/interface/generator/function_param_list.py +0 -2
  15. classiq/interface/generator/generated_circuit_data.py +1 -6
  16. classiq/interface/generator/quantum_program.py +0 -4
  17. classiq/interface/generator/transpiler_basis_gates.py +3 -0
  18. classiq/interface/generator/types/builtin_enum_declarations.py +0 -9
  19. classiq/interface/interface_version.py +1 -1
  20. classiq/interface/model/block.py +4 -0
  21. classiq/interface/model/classical_if.py +4 -0
  22. classiq/interface/model/control.py +7 -0
  23. classiq/interface/model/invert.py +4 -0
  24. classiq/interface/model/model_visitor.py +40 -1
  25. classiq/interface/model/power.py +4 -0
  26. classiq/interface/model/quantum_statement.py +8 -1
  27. classiq/interface/model/repeat.py +4 -0
  28. classiq/interface/model/skip_control.py +4 -0
  29. classiq/interface/model/within_apply_operation.py +4 -0
  30. classiq/model_expansions/interpreters/base_interpreter.py +1 -1
  31. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
  32. classiq/model_expansions/visitors/symbolic_param_inference.py +3 -3
  33. classiq/model_expansions/visitors/uncomputation_signature_inference.py +14 -3
  34. classiq/open_library/functions/__init__.py +4 -1
  35. classiq/open_library/functions/amplitude_loading.py +66 -0
  36. classiq/open_library/functions/lookup_table.py +22 -9
  37. classiq/open_library/functions/modular_exponentiation.py +5 -8
  38. classiq/open_library/functions/qsvt.py +4 -4
  39. classiq/qmod/builtins/classical_execution_primitives.py +0 -12
  40. classiq/qmod/builtins/enums.py +15 -17
  41. classiq/qmod/builtins/functions/__init__.py +3 -5
  42. classiq/qmod/builtins/functions/mcx.py +7 -0
  43. classiq/qmod/builtins/operations.py +60 -22
  44. classiq/qmod/builtins/structs.py +22 -33
  45. classiq/qmod/semantics/annotation/call_annotation.py +3 -3
  46. classiq/qmod/semantics/error_manager.py +7 -8
  47. {classiq-0.94.1.dist-info → classiq-0.95.0.dist-info}/METADATA +1 -1
  48. {classiq-0.94.1.dist-info → classiq-0.95.0.dist-info}/RECORD +50 -51
  49. {classiq-0.94.1.dist-info → classiq-0.95.0.dist-info}/WHEEL +1 -1
  50. classiq/applications/qsvm/__init__.py +0 -8
  51. classiq/applications/qsvm/qsvm.py +0 -11
  52. classiq/interface/applications/qsvm.py +0 -114
  53. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
  54. classiq/interface/generator/qsvm.py +0 -96
  55. classiq/qmod/builtins/functions/qsvm.py +0 -24
  56. {classiq-0.94.1.dist-info → classiq-0.95.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  from collections.abc import Callable, Iterable, Mapping, Sequence
2
2
  from dataclasses import dataclass
3
- from typing import Any
3
+ from typing import TYPE_CHECKING, Any
4
4
  from uuid import UUID, uuid4
5
5
 
6
6
  import pydantic
@@ -17,6 +17,9 @@ from classiq.interface.model.handle_binding import (
17
17
  HandleBinding,
18
18
  )
19
19
 
20
+ if TYPE_CHECKING:
21
+ from classiq.interface.model.statement_block import StatementBlock
22
+
20
23
 
21
24
  class QuantumStatement(ASTNode):
22
25
  kind: str
@@ -45,6 +48,10 @@ class QuantumStatement(ASTNode):
45
48
  def expressions(self) -> list[Expression]:
46
49
  return []
47
50
 
51
+ @property
52
+ def blocks(self) -> dict[str, "StatementBlock"]:
53
+ return {}
54
+
48
55
 
49
56
  @dataclass
50
57
  class HandleMetadata:
@@ -21,3 +21,7 @@ class Repeat(QuantumOperation):
21
21
  @property
22
22
  def expressions(self) -> list[Expression]:
23
23
  return [self.count]
24
+
25
+ @property
26
+ def blocks(self) -> dict[str, "StatementBlock"]:
27
+ return {"body": self.body}
@@ -9,3 +9,7 @@ if TYPE_CHECKING:
9
9
  class SkipControl(QuantumOperation):
10
10
  kind: Literal["SkipControl"]
11
11
  body: "StatementBlock"
12
+
13
+ @property
14
+ def blocks(self) -> dict[str, "StatementBlock"]:
15
+ return {"body": self.body}
@@ -16,6 +16,10 @@ class WithinApply(QuantumOperation):
16
16
  def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
17
17
  return reset_lists(self, ["compute", "action"])
18
18
 
19
+ @property
20
+ def blocks(self) -> dict[str, "StatementBlock"]:
21
+ return {"compute": self.compute, "action": self.action}
22
+
19
23
 
20
24
  class Compute(QuantumOperation):
21
25
  kind: Literal["Compute"]
@@ -324,7 +324,7 @@ class BaseInterpreter:
324
324
  def emit_statement(self, statement: QuantumStatement) -> None:
325
325
  source_ref = statement.source_ref
326
326
  error_context = (
327
- self._error_manager.node_context(statement)
327
+ self._error_manager.source_ref_context(statement.source_ref)
328
328
  if source_ref is not None
329
329
  else nullcontext()
330
330
  )
@@ -41,7 +41,8 @@ class FrontendGenerativeInterpreter(GenerativeInterpreter):
41
41
  if module is None or not module.__name__.startswith("classiq."):
42
42
  file_name = os.path.split(frame.filename)[-1]
43
43
  if (
44
- frame.positions is not None
44
+ hasattr(frame, "positions")
45
+ and frame.positions is not None
45
46
  and frame.positions.lineno is not None
46
47
  and frame.positions.col_offset is not None
47
48
  and frame.positions.end_lineno is not None
@@ -19,7 +19,7 @@ from classiq.interface.model.classical_parameter_declaration import (
19
19
  AnonClassicalParameterDeclaration,
20
20
  )
21
21
  from classiq.interface.model.handle_binding import FieldHandleBinding, HandleBinding
22
- from classiq.interface.model.model_visitor import ModelVisitor
22
+ from classiq.interface.model.model_visitor import ModelStatementsVisitor
23
23
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
24
24
  from classiq.interface.model.quantum_function_call import ArgValue, QuantumFunctionCall
25
25
  from classiq.interface.model.quantum_function_declaration import (
@@ -84,7 +84,7 @@ def _get_param_expressions(param: AnonPositionalArg) -> list[Expression]:
84
84
  return param.quantum_type.expressions
85
85
 
86
86
 
87
- class SymbolicParamInference(ModelVisitor):
87
+ class SymbolicParamInference(ModelStatementsVisitor):
88
88
  def __init__(
89
89
  self,
90
90
  functions: list[NativeFunctionDefinition],
@@ -166,7 +166,7 @@ class SymbolicParamInference(ModelVisitor):
166
166
  else:
167
167
  for expr in _get_expressions(arg):
168
168
  self._process_nested_compile_time_expression(expr.expr)
169
- self.generic_visit(call)
169
+ self.visit(call.positional_args)
170
170
 
171
171
  def _get_params(self, call: QuantumFunctionCall) -> Sequence[AnonPositionalArg]:
172
172
  name = call.func_name
@@ -18,9 +18,10 @@ from classiq.interface.generator.visitor import NodeType
18
18
  from classiq.interface.model.allocate import Allocate
19
19
  from classiq.interface.model.bind_operation import BindOperation
20
20
  from classiq.interface.model.block import Block
21
+ from classiq.interface.model.classical_if import ClassicalIf
21
22
  from classiq.interface.model.control import Control
22
23
  from classiq.interface.model.invert import Invert
23
- from classiq.interface.model.model_visitor import ModelVisitor
24
+ from classiq.interface.model.model_visitor import ModelStatementsVisitor
24
25
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
25
26
  from classiq.interface.model.power import Power
26
27
  from classiq.interface.model.quantum_expressions.amplitude_loading_operation import (
@@ -48,7 +49,7 @@ class _BoundVars(NamedTuple):
48
49
  )
49
50
 
50
51
 
51
- class UncomputationSignatureInference(ModelVisitor):
52
+ class UncomputationSignatureInference(ModelStatementsVisitor):
52
53
  """
53
54
  Infers the uncomputation signature of a function (permutation/non-permutation for
54
55
  the function, and const/non-const for each parameter).
@@ -139,7 +140,13 @@ class UncomputationSignatureInference(ModelVisitor):
139
140
  self._bound_vars_list.append(bound_vars)
140
141
 
141
142
  def visit_ArithmeticOperation(self, arith: ArithmeticOperation) -> None:
142
- self._mark_as_non_const(arith.result_var.name, True)
143
+ if arith.classical_assignment:
144
+ if arith.var_handles:
145
+ self._mark_as_non_permutation()
146
+ for handle in arith.var_handles:
147
+ self._mark_as_non_const(handle.name, False)
148
+ else:
149
+ self._mark_as_non_const(arith.result_var.name, True)
143
150
 
144
151
  def visit_AmplitudeLoadingOperation(
145
152
  self, amp_load: AmplitudeLoadingOperation
@@ -172,6 +179,10 @@ class UncomputationSignatureInference(ModelVisitor):
172
179
  def visit_SkipControl(self, block: SkipControl) -> None:
173
180
  self.visit(block.body)
174
181
 
182
+ def visit_ClassicalIf(self, classical_if: ClassicalIf) -> None:
183
+ self.visit(classical_if.then)
184
+ self.visit(classical_if.else_)
185
+
175
186
  def _mark_as_non_permutation(self) -> None:
176
187
  self._is_permutation = False
177
188
  self._non_permutation_reasons.append(self._source_ref)
@@ -3,6 +3,7 @@ from .amplitude_amplification import (
3
3
  exact_amplitude_amplification,
4
4
  )
5
5
  from .amplitude_estimation import *
6
+ from .amplitude_loading import load_amplitudes
6
7
  from .discrete_sine_cosine_transform import *
7
8
  from .discrete_sine_cosine_transform import _qct_d_operator, _qct_pi_operator
8
9
  from .grover import *
@@ -11,7 +12,7 @@ from .hea import *
11
12
  from .lcu import *
12
13
  from .linear_pauli_rotation import *
13
14
  from .linear_pauli_rotation import _single_pauli
14
- from .lookup_table import span_lookup_table
15
+ from .lookup_table import get_lookup_table, span_lookup_table
15
16
  from .modular_exponentiation import *
16
17
  from .modular_exponentiation import _check_msb
17
18
  from .qaoa_penalty import *
@@ -98,6 +99,7 @@ __all__ = [
98
99
  "encode_on_bloch",
99
100
  "exact_amplitude_amplification",
100
101
  "full_hea",
102
+ "get_lookup_table",
101
103
  "gqsp",
102
104
  "grover_diffuser",
103
105
  "grover_operator",
@@ -111,6 +113,7 @@ __all__ = [
111
113
  "lcu",
112
114
  "lcu_pauli",
113
115
  "linear_pauli_rotations",
116
+ "load_amplitudes",
114
117
  "modular_add_qft_space",
115
118
  "modular_exp",
116
119
  "modular_increment",
@@ -0,0 +1,66 @@
1
+ from typing import cast
2
+
3
+ import numpy as np
4
+ from sympy import fwht
5
+
6
+ from classiq.interface.exceptions import ClassiqValueError
7
+
8
+ from classiq.qmod.builtins.functions import CX, RY
9
+ from classiq.qmod.builtins.operations import bind, skip_control
10
+ from classiq.qmod.qfunc import qfunc
11
+ from classiq.qmod.qmod_variable import QArray, QBit, QNum
12
+
13
+
14
+ def _get_graycode(size: int, i: int) -> int:
15
+ if i == 2**size:
16
+ return _get_graycode(size, 0)
17
+ return i ^ (i >> 1)
18
+
19
+
20
+ def _get_graycode_angles_wh(size: int, angles: list[float]) -> list[float]:
21
+ transformed_angles = fwht(np.array(angles) / 2**size)
22
+ return [transformed_angles[_get_graycode(size, j)] for j in range(2**size)]
23
+
24
+
25
+ def _get_graycode_ctrls(size: int) -> list[int]:
26
+ return [
27
+ (_get_graycode(size, i) ^ _get_graycode(size, i + 1)).bit_length() - 1
28
+ for i in range(2**size)
29
+ ]
30
+
31
+
32
+ @qfunc
33
+ def load_amplitudes(amplitudes: list[float], index: QNum, indicator: QBit) -> None:
34
+ """
35
+ [Qmod Classiq-library function]
36
+
37
+ Load a specified list of real amplitudes into a quantum variable using an extra indicator qubit:
38
+ \\( |i\rangle|0\rangle \rightarrow a(i)\\,|i\rangle|1\rangle + \\sqrt{1 - a(i)^2}\\,|x\rangle|0\rangle \\).
39
+ Here, \\(a(i)\\) is the i-th amplitude, determined by the QNum when the index is in state \\(i\\).
40
+ A list extracted from a given classical function \\(f(x)\\), with indexing according to a given QNum, can be obtained via the utility SDK function `get_lookup_table`.
41
+ This function expects the indicator qubit to be initialized to \\(|0\rangle\\).
42
+
43
+ Args:
44
+ amplitudes: Real values for the amplitudes
45
+ index: The quantum variable used for amplitude indexing
46
+ indicator: The quantum indicator qubit
47
+ """
48
+ if len(amplitudes) != 2**index.size:
49
+ raise ClassiqValueError(
50
+ f"The number of amplitudes must be 2**index.size={2 ** index.size}, got "
51
+ f"{len(amplitudes)}"
52
+ )
53
+
54
+ angles_to_load = cast(list[float], 2 * np.arcsin(amplitudes))
55
+ size = cast(int, index.size)
56
+ transformed_angles = _get_graycode_angles_wh(size, angles_to_load)
57
+ controllers = _get_graycode_ctrls(size)
58
+
59
+ qba: QArray = QArray()
60
+ bind(index, qba)
61
+ for k in range(2**size):
62
+ RY(transformed_angles[k], indicator)
63
+ skip_control(
64
+ lambda k=k: CX(qba[controllers[k]], indicator) # type:ignore[misc]
65
+ )
66
+ bind(qba, index)
@@ -17,13 +17,30 @@ def _get_qnum_values(num: QNum) -> list[float]:
17
17
  or not isinstance(is_signed, bool)
18
18
  or not isinstance(fraction_digits, int)
19
19
  ):
20
- raise ClassiqValueError(
21
- "Must call 'span_lookup_table' inside a generative qfunc"
22
- )
20
+ raise ClassiqValueError(f"QNum argument {str(num)!r} has symbolic attributes")
23
21
 
24
22
  return qnum_values(size, is_signed, fraction_digits)
25
23
 
26
24
 
25
+ def get_lookup_table(func: RealFunction, *targets: QNum) -> list[float]:
26
+ """
27
+ Reduces a classical function into a lookup table over all the possible values
28
+ of the quantum numbers.
29
+
30
+ Args:
31
+ func: A Python function
32
+ *targets: One or more initialized quantum numbers
33
+
34
+ Returns:
35
+ The function's lookup table
36
+
37
+ Notes:
38
+ The QNum arguments must have generative attributes
39
+ """
40
+ target_vals = [_get_qnum_values(target) for target in targets]
41
+ return [func(*vals[::-1]) for vals in product(*target_vals[::-1])]
42
+
43
+
27
44
  def span_lookup_table(func: RealFunction, *targets: QNum) -> QNum:
28
45
  """
29
46
  Applies a classical function to quantum numbers.
@@ -39,13 +56,9 @@ def span_lookup_table(func: RealFunction, *targets: QNum) -> QNum:
39
56
  The quantum result of applying func to targets
40
57
 
41
58
  Notes:
42
- Must be called inside a generative function (`@qfunc`)
59
+ The QNum arguments must have generative attributes
43
60
  """
44
- if len(targets) == 0:
45
- raise ClassiqValueError("No targets specified")
46
-
47
- target_vals = [_get_qnum_values(target) for target in targets]
48
- lookup_table = [func(*vals[::-1]) for vals in product(*target_vals[::-1])]
61
+ lookup_table = get_lookup_table(func, *targets)
49
62
 
50
63
  index_size = sum(target.size for target in targets)
51
64
  index: QNum = QNum(get_temp_var_name(), size=index_size)
@@ -242,14 +242,11 @@ def inplace_modular_multiply(n: CInt, a: CInt, x: QArray[QBit]) -> None:
242
242
  Comment: It is assumed that `a` has an inverse modulo `n`
243
243
  """
244
244
  b: QArray[QBit] = QArray(length=x.len + 1)
245
- within_apply(
246
- lambda: allocate(b),
247
- lambda: (
248
- modular_multiply(n, a, b, x),
249
- multiswap(x, b),
250
- invert(lambda: modular_multiply(n, mod_inverse(a, n), b, x)),
251
- ),
252
- )
245
+ allocate(b)
246
+ modular_multiply(n, a, b, x)
247
+ multiswap(x, b)
248
+ invert(lambda: modular_multiply(n, mod_inverse(a, n), b, x))
249
+ free(b)
253
250
 
254
251
 
255
252
  @qfunc
@@ -195,7 +195,7 @@ def projector_controlled_double_phase(
195
195
  """
196
196
  within_apply(
197
197
  lambda: proj_cnot(qvar, aux),
198
- lambda: control(lcu, lambda: RZ(phase_even, aux), lambda: RZ(phase_odd, aux)),
198
+ lambda: control(lcu, lambda: RZ(phase_odd, aux), lambda: RZ(phase_even, aux)),
199
199
  )
200
200
 
201
201
 
@@ -262,7 +262,7 @@ def qsvt_lcu(
262
262
 
263
263
  The function is intended to be called within a context of LCU, where it is called as the SELECT operator, and wrapped
264
264
  with initialization of the `lcu` qubit to get the desired combination coefficients.
265
- The even polynomial corresponds to the case where the $lcu=|0\\rangle$, while the odd to #lcu=|1\\rangle$.
265
+ The even polynomial corresponds to the case where the $lcu=|0\\rangle$, while the odd to $lcu=|1\\rangle$.
266
266
 
267
267
  Note: the two polynomials should have the same degree up to a difference of 1.
268
268
 
@@ -296,7 +296,7 @@ def qsvt_lcu(
296
296
  if_(
297
297
  condition=phase_seq_odd.len > phase_seq_even.len,
298
298
  then=lambda: control(
299
- lcu == 0,
299
+ lcu,
300
300
  lambda: [
301
301
  u(qvar),
302
302
  projector_controlled_phase(
@@ -318,7 +318,7 @@ def qsvt_lcu(
318
318
  lcu,
319
319
  ),
320
320
  control(
321
- lcu,
321
+ lcu == 0,
322
322
  lambda: [
323
323
  invert(lambda: u(qvar)),
324
324
  projector_controlled_phase(
@@ -13,7 +13,6 @@ from classiq.interface.executor.result import (
13
13
  from classiq.interface.executor.vqe_result import VQESolverResult
14
14
  from classiq.interface.generator.functions.qmod_python_interface import QmodPyStruct
15
15
 
16
- from classiq.applications.qsvm.qsvm import Data, Labels
17
16
  from classiq.qmod.builtins.enums import Optimizer
18
17
 
19
18
  _CALL_IN_QFUNC_ERROR = (
@@ -78,16 +77,6 @@ def qae_with_qpe_result_post_processing( # type: ignore[return]
78
77
  _raise_error("qae_with_qpe_result_post_processing")
79
78
 
80
79
 
81
- def qsvm_full_run( # type: ignore[return]
82
- train_data: Data,
83
- train_labels: Labels,
84
- test_data: Data,
85
- test_labels: Labels,
86
- predict_data: Data,
87
- ) -> QmodPyStruct:
88
- _raise_error("qsvm_full_run")
89
-
90
-
91
80
  def iqae( # type: ignore[return]
92
81
  epsilon: float,
93
82
  alpha: float,
@@ -102,7 +91,6 @@ __all__ = [
102
91
  "estimate",
103
92
  "iqae",
104
93
  "qae_with_qpe_result_post_processing",
105
- "qsvm_full_run",
106
94
  "sample",
107
95
  "save",
108
96
  "vqe",
@@ -2,6 +2,7 @@ from enum import IntEnum
2
2
  from typing import TYPE_CHECKING
3
3
 
4
4
  from classiq.interface.generator.types.enum_declaration import EnumDeclaration
5
+ from classiq.interface.helpers.datastructures import LenList
5
6
 
6
7
  if TYPE_CHECKING:
7
8
  from classiq.qmod.builtins.structs import SparsePauliOp
@@ -62,26 +63,24 @@ class Pauli(IntEnum):
62
63
  )
63
64
 
64
65
  return SparsePauliOp(
65
- terms=[
66
- SparsePauliTerm(
67
- paulis=[ # type:ignore[arg-type]
68
- IndexedPauli(pauli=self, index=index) # type:ignore[arg-type]
69
- ],
70
- coefficient=1.0, # type:ignore[arg-type]
71
- )
72
- ],
66
+ terms=LenList(
67
+ [
68
+ SparsePauliTerm(
69
+ paulis=LenList(
70
+ [ # type:ignore[arg-type]
71
+ IndexedPauli(
72
+ pauli=self, index=index # type:ignore[arg-type]
73
+ )
74
+ ]
75
+ ),
76
+ coefficient=1.0, # type:ignore[arg-type]
77
+ )
78
+ ]
79
+ ),
73
80
  num_qubits=index + 1,
74
81
  )
75
82
 
76
83
 
77
- class QSVMFeatureMapEntanglement(IntEnum):
78
- FULL = 0
79
- LINEAR = 1
80
- CIRCULAR = 2
81
- SCA = 3
82
- PAIRWISE = 4
83
-
84
-
85
84
  BUILTIN_ENUM_DECLARATIONS = {
86
85
  enum_def.__name__: EnumDeclaration(
87
86
  name=enum_def.__name__,
@@ -98,5 +97,4 @@ BUILTIN_ENUM_DECLARATIONS = {
98
97
  __all__ = [
99
98
  "Optimizer",
100
99
  "Pauli",
101
- "QSVMFeatureMapEntanglement",
102
100
  ]
@@ -2,16 +2,14 @@ from .allocation import *
2
2
  from .arithmetic import *
3
3
  from .benchmarking import *
4
4
  from .exponentiation import *
5
+ from .mcx import MCX
5
6
  from .mid_circuit_measurement import *
6
7
  from .operators import *
7
- from .qsvm import *
8
8
  from .standard_gates import *
9
9
 
10
10
  CORE_LIB_DECLS = [
11
11
  func.func_decl
12
12
  for func in (
13
- pauli_feature_map,
14
- bloch_sphere_feature_map,
15
13
  H,
16
14
  X,
17
15
  Y,
@@ -67,6 +65,7 @@ CORE_LIB_DECLS = [
67
65
  qdrift,
68
66
  exponentiation_with_depth_constraint,
69
67
  RESET,
68
+ MCX,
70
69
  )
71
70
  ]
72
71
 
@@ -85,6 +84,7 @@ __all__ = [ # noqa: RUF022
85
84
  "H",
86
85
  "I",
87
86
  "IDENTITY",
87
+ "MCX",
88
88
  "PHASE",
89
89
  "R",
90
90
  "RX",
@@ -105,7 +105,6 @@ __all__ = [ # noqa: RUF022
105
105
  "add",
106
106
  "add_inplace_right",
107
107
  "apply",
108
- "bloch_sphere_feature_map",
109
108
  "exponentiation_with_depth_constraint",
110
109
  "free",
111
110
  "inplace_prepare_amplitudes",
@@ -117,7 +116,6 @@ __all__ = [ # noqa: RUF022
117
116
  "modular_add_constant",
118
117
  "multi_suzuki_trotter",
119
118
  "parametric_suzuki_trotter",
120
- "pauli_feature_map",
121
119
  "permute",
122
120
  "prepare_amplitudes",
123
121
  "prepare_amplitudes_approx",
@@ -0,0 +1,7 @@
1
+ from classiq.qmod.qfunc import qperm
2
+ from classiq.qmod.qmod_variable import Const, QArray, QBit
3
+
4
+
5
+ @qperm(external=True)
6
+ def MCX(ctrl: Const[QArray[QBit]], target: QBit) -> None:
7
+ pass