classiq 0.94.2__py3-none-any.whl → 0.96.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 (76) hide show
  1. classiq/_internals/api_wrapper.py +0 -83
  2. classiq/_internals/authentication/auth0.py +32 -3
  3. classiq/_internals/authentication/authorization_code.py +9 -0
  4. classiq/_internals/authentication/authorization_flow.py +41 -0
  5. classiq/_internals/authentication/device.py +31 -50
  6. classiq/_internals/authentication/hybrid_flow.py +19 -0
  7. classiq/_internals/authentication/token_manager.py +5 -4
  8. classiq/applications/__init__.py +2 -2
  9. classiq/applications/iqae/iqae.py +6 -3
  10. classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
  11. classiq/applications/qnn/qlayer.py +1 -1
  12. classiq/applications/qnn/torch_utils.py +2 -2
  13. classiq/applications/qsp/qsp.py +6 -5
  14. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +10 -0
  15. classiq/execution/__init__.py +0 -3
  16. classiq/execution/user_budgets.py +0 -1
  17. classiq/interface/_version.py +1 -1
  18. classiq/interface/backend/backend_preferences.py +11 -35
  19. classiq/interface/backend/quantum_backend_providers.py +0 -2
  20. classiq/interface/exceptions.py +0 -4
  21. classiq/interface/generator/application_apis/__init__.py +0 -1
  22. classiq/interface/generator/arith/register_user_input.py +1 -1
  23. classiq/interface/generator/function_param_list.py +0 -2
  24. classiq/interface/generator/generated_circuit_data.py +1 -6
  25. classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
  26. classiq/interface/generator/quantum_function_call.py +1 -1
  27. classiq/interface/generator/quantum_program.py +0 -4
  28. classiq/interface/generator/transpiler_basis_gates.py +3 -0
  29. classiq/interface/generator/types/builtin_enum_declarations.py +0 -9
  30. classiq/interface/hardware.py +0 -1
  31. classiq/interface/interface_version.py +1 -1
  32. classiq/interface/model/block.py +4 -0
  33. classiq/interface/model/classical_if.py +4 -0
  34. classiq/interface/model/control.py +7 -0
  35. classiq/interface/model/invert.py +4 -0
  36. classiq/interface/model/model_visitor.py +40 -1
  37. classiq/interface/model/power.py +4 -0
  38. classiq/interface/model/quantum_statement.py +8 -1
  39. classiq/interface/model/repeat.py +4 -0
  40. classiq/interface/model/skip_control.py +4 -0
  41. classiq/interface/model/within_apply_operation.py +4 -0
  42. classiq/interface/server/routes.py +0 -12
  43. classiq/model_expansions/generative_functions.py +6 -8
  44. classiq/model_expansions/interpreters/base_interpreter.py +1 -1
  45. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
  46. classiq/model_expansions/visitors/symbolic_param_inference.py +3 -3
  47. classiq/model_expansions/visitors/uncomputation_signature_inference.py +14 -3
  48. classiq/open_library/functions/__init__.py +3 -2
  49. classiq/open_library/functions/amplitude_loading.py +85 -0
  50. classiq/open_library/functions/lcu.py +47 -18
  51. classiq/open_library/functions/modular_exponentiation.py +5 -8
  52. classiq/open_library/functions/qsvt.py +4 -4
  53. classiq/open_library/functions/state_preparation.py +7 -7
  54. classiq/qmod/builtins/classical_execution_primitives.py +0 -12
  55. classiq/qmod/builtins/enums.py +15 -17
  56. classiq/qmod/builtins/functions/__init__.py +5 -5
  57. classiq/qmod/builtins/functions/allocation.py +21 -0
  58. classiq/qmod/builtins/functions/mcx.py +7 -0
  59. classiq/qmod/builtins/operations.py +125 -23
  60. classiq/qmod/builtins/structs.py +22 -33
  61. classiq/qmod/semantics/annotation/call_annotation.py +3 -3
  62. classiq/qmod/semantics/error_manager.py +7 -8
  63. classiq/qmod/utilities.py +0 -10
  64. {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/METADATA +1 -1
  65. {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/RECORD +67 -71
  66. {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/WHEEL +1 -1
  67. classiq/applications/qsvm/__init__.py +0 -8
  68. classiq/applications/qsvm/qsvm.py +0 -11
  69. classiq/execution/iqcc.py +0 -128
  70. classiq/interface/applications/qsvm.py +0 -114
  71. classiq/interface/execution/iqcc.py +0 -42
  72. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
  73. classiq/interface/generator/qsvm.py +0 -96
  74. classiq/open_library/functions/lookup_table.py +0 -58
  75. classiq/qmod/builtins/functions/qsvm.py +0 -24
  76. {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -9,6 +9,7 @@ from classiq.open_library.functions.utility_functions import switch
9
9
  from classiq.qmod.builtins.functions import IDENTITY, X, Y, Z, inplace_prepare_state
10
10
  from classiq.qmod.builtins.operations import (
11
11
  control,
12
+ if_,
12
13
  repeat,
13
14
  within_apply,
14
15
  )
@@ -16,7 +17,7 @@ from classiq.qmod.builtins.structs import IndexedPauli, SparsePauliOp
16
17
  from classiq.qmod.cparam import CArray
17
18
  from classiq.qmod.qfunc import qfunc
18
19
  from classiq.qmod.qmod_variable import QArray, QBit, QNum
19
- from classiq.qmod.quantum_callable import QCallableList
20
+ from classiq.qmod.quantum_callable import QCallable, QCallableList
20
21
 
21
22
 
22
23
  @qfunc
@@ -36,27 +37,23 @@ def apply_pauli_term(pauli_string: CArray[IndexedPauli], x: QArray[QBit]) -> Non
36
37
 
37
38
 
38
39
  @qfunc
39
- def lcu(
40
+ def prepare_select(
40
41
  coefficients: list[float],
41
- unitaries: QCallableList,
42
+ select: QCallable[QNum],
42
43
  block: QNum[Literal["max(ceiling(log(coefficients.len, 2)), 1)"]],
43
44
  ) -> None:
44
45
  """
45
46
  [Qmod Classiq-library function]
46
47
 
47
- Implements a general linear combination of unitaries (LCU) procedure. The algorithm prepares a superposition
48
- over the `unitaries` according to `magnitudes`, and then conditionally applies each unitary controlled by the `block`.
49
-
50
- The operation is of the form:
51
-
52
- $$\\sum_j \\alpha_j U_j$$
53
-
54
- where $U_j$ is a unitary operation applied to `data`.
48
+ Applies the 'Prepare-Select' scheme used for Linear Combination of Unitaries (LCU).
49
+ Compared to the `lcu` function, here the Select operator should be provided directly, allowing to take advantage of some structure for
50
+ the unitaries of the LCU.
51
+ The select operator is defined by: $\\mathrm{SELECT} = \\sum_{j=0}^{m-1} |j\rangle\\!\\langle j|_{block} \\otimes U_j$.
55
52
 
56
53
  Args:
57
54
  coefficients: L1-normalized array of $\\{ \\alpha_j \\}$ of the LCU coefficients.
58
- unitaries: A list of quantum callable functions to be applied conditionally.
59
- block: Quantum variable that holds the superposition index used for conditional application of each unitary.
55
+ select: A quantum callable to be applied between the state preparation and its inverse. Its input is the `block` variable, labeling the index of the unitaries in the LCU.
56
+ block: A Quantum variable that holds the index used as input for the 'select' operator.
60
57
  """
61
58
  coefficients = coefficients + [0] * (
62
59
  2**block.size - len(coefficients) # type:ignore[operator]
@@ -68,16 +65,48 @@ def lcu(
68
65
  within_apply(
69
66
  lambda: inplace_prepare_state(magnitudes, 0, block),
70
67
  lambda: [
71
- repeat(
72
- count=unitaries.len,
73
- iteration=lambda i: control(block == i, lambda: unitaries[i]()),
68
+ select(block),
69
+ if_(
70
+ not np.allclose(np.array(phases) % (2 * np.pi), 0),
71
+ lambda: apply_phase_table(phases, block),
74
72
  ),
75
- # TODO: replace to sparse constant phase
76
- apply_phase_table(phases, block),
77
73
  ],
78
74
  )
79
75
 
80
76
 
77
+ @qfunc
78
+ def lcu(
79
+ coefficients: list[float],
80
+ unitaries: QCallableList,
81
+ block: QNum[Literal["max(ceiling(log(coefficients.len, 2)), 1)"]],
82
+ ) -> None:
83
+ """
84
+ [Qmod Classiq-library function]
85
+
86
+ Implements a general linear combination of unitaries (LCU) procedure. The algorithm prepares a superposition
87
+ over the `unitaries` according to the given `coefficients`, and then conditionally applies each unitary controlled by the `block`.
88
+
89
+ The operation is of the form:
90
+
91
+ $$\\sum_j \\alpha_j U_j$$
92
+
93
+ where $U_j$ is a unitary operation applied to `data`.
94
+
95
+ Args:
96
+ coefficients: L1-normalized array of $\\{ \\alpha_j \\}$ of the LCU coefficients.
97
+ unitaries: A list of quantum callable functions to be applied conditionally.
98
+ block: Quantum variable that holds the superposition index used for conditional application of each unitary.
99
+ """
100
+ prepare_select(
101
+ coefficients,
102
+ lambda _block: repeat(
103
+ count=unitaries.len,
104
+ iteration=lambda i: control(_block == i, lambda: unitaries[i]()),
105
+ ),
106
+ block,
107
+ )
108
+
109
+
81
110
  @qfunc
82
111
  def lcu_pauli(
83
112
  operator: SparsePauliOp,
@@ -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(
@@ -29,7 +29,7 @@ from classiq.qmod.builtins.operations import (
29
29
  within_apply,
30
30
  )
31
31
  from classiq.qmod.cparam import CArray, CInt, CReal
32
- from classiq.qmod.qfunc import qfunc
32
+ from classiq.qmod.qfunc import qfunc, qperm
33
33
  from classiq.qmod.qmod_variable import Output, QArray, QBit, QNum
34
34
  from classiq.qmod.symbolic import (
35
35
  acos,
@@ -248,7 +248,7 @@ def prepare_bell_state(
248
248
  CX(qpair[0], qpair[1])
249
249
 
250
250
 
251
- @qfunc
251
+ @qperm
252
252
  def inplace_prepare_int(value: CInt, target: QNum) -> None:
253
253
  """
254
254
  [Qmod Classiq-library function]
@@ -273,7 +273,7 @@ def inplace_prepare_int(value: CInt, target: QNum) -> None:
273
273
  target ^= value
274
274
 
275
275
 
276
- @qfunc
276
+ @qperm
277
277
  def prepare_int(
278
278
  value: CInt,
279
279
  out: Output[QNum[Literal["floor(log(value, 2)) + 1"]]],
@@ -324,7 +324,7 @@ def _classical_hadamard_transform(arr: list[float]) -> np.ndarray:
324
324
  return 1 / np.sqrt(len(arr)) * np.array(sympy.fwht(np.array(arr)))
325
325
 
326
326
 
327
- @qfunc
327
+ @qperm
328
328
  def apply_phase_table(
329
329
  phases: list[float],
330
330
  target: QArray[QBit, Literal["log(phases.len, 2)"]],
@@ -456,7 +456,7 @@ def prepare_dicke_state(k: int, qvar: QArray[QBit]) -> None:
456
456
  prepare_dicke_state_unary_input(k, qvar)
457
457
 
458
458
 
459
- @qfunc
459
+ @qperm
460
460
  def prepare_basis_state(state: list[bool], arr: Output[QArray]) -> None:
461
461
  """
462
462
  [Qmod Classiq-library function]
@@ -515,7 +515,7 @@ def prepare_linear_amplitudes(x: QArray) -> None:
515
515
  hadamard_transform(x)
516
516
 
517
517
 
518
- @qfunc
518
+ @qperm
519
519
  def swap_states(a: int, b: int, target: QArray) -> None:
520
520
  """
521
521
  Swap 2 computational basis states a and b, leave all other states untouched.
@@ -538,7 +538,7 @@ def swap_states(a: int, b: int, target: QArray) -> None:
538
538
  if anchor < target.len - 1:
539
539
  target_without_anchor.append(target[anchor + 1 : target.len])
540
540
 
541
- @qfunc
541
+ @qperm
542
542
  def _xor_if_equal(n: CInt, ctrl: QNum, target: QBit) -> None:
543
543
  target ^= ctrl == n
544
544
 
@@ -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,
@@ -53,6 +51,7 @@ CORE_LIB_DECLS = [
53
51
  U,
54
52
  CCX,
55
53
  free,
54
+ drop,
56
55
  randomized_benchmarking,
57
56
  inplace_prepare_state,
58
57
  inplace_prepare_state_approx,
@@ -67,6 +66,7 @@ CORE_LIB_DECLS = [
67
66
  qdrift,
68
67
  exponentiation_with_depth_constraint,
69
68
  RESET,
69
+ MCX,
70
70
  )
71
71
  ]
72
72
 
@@ -85,6 +85,7 @@ __all__ = [ # noqa: RUF022
85
85
  "H",
86
86
  "I",
87
87
  "IDENTITY",
88
+ "MCX",
88
89
  "PHASE",
89
90
  "R",
90
91
  "RX",
@@ -105,9 +106,9 @@ __all__ = [ # noqa: RUF022
105
106
  "add",
106
107
  "add_inplace_right",
107
108
  "apply",
108
- "bloch_sphere_feature_map",
109
109
  "exponentiation_with_depth_constraint",
110
110
  "free",
111
+ "drop",
111
112
  "inplace_prepare_amplitudes",
112
113
  "inplace_prepare_amplitudes_approx",
113
114
  "inplace_prepare_state",
@@ -117,7 +118,6 @@ __all__ = [ # noqa: RUF022
117
118
  "modular_add_constant",
118
119
  "multi_suzuki_trotter",
119
120
  "parametric_suzuki_trotter",
120
- "pauli_feature_map",
121
121
  "permute",
122
122
  "prepare_amplitudes",
123
123
  "prepare_amplitudes_approx",
@@ -21,6 +21,27 @@ def free(in_: Input[QArray[QBit]]) -> None:
21
21
  pass
22
22
 
23
23
 
24
+ @qperm(external=True)
25
+ def drop(in_: Input[QArray[QBit]]) -> None:
26
+ """
27
+ [Qmod core-library function]
28
+
29
+ Discards the qubits allocated to a quantum variable which may be in any state,
30
+ preventing their further use.
31
+
32
+ Args:
33
+ in_: The quantum variable that will be dropped. Must be initialized before.
34
+
35
+ Note:
36
+ This operation can be used to bypass the restrictions on a local variable
37
+ that enable its uncomputation. The implication is that its qubits are left
38
+ dirty, possibly entangled with functional qubits, and never subsequently reused.
39
+
40
+ Functions which use `drop` cannot be inverted or used inside a _within_ block.
41
+ """
42
+ pass
43
+
44
+
24
45
  @qfunc(external=True)
25
46
  def prepare_state(
26
47
  probabilities: CArray[CReal],
@@ -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