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
@@ -1,11 +1,15 @@
1
1
  import inspect
2
2
  import sys
3
3
  from collections.abc import Callable, Mapping
4
+ from functools import wraps
5
+ from itertools import product
4
6
  from types import FrameType
5
7
  from typing import (
6
8
  Any,
7
9
  Final,
8
10
  NoReturn,
11
+ ParamSpec,
12
+ TypeVar,
9
13
  overload,
10
14
  )
11
15
 
@@ -45,16 +49,37 @@ from classiq.interface.model.skip_control import SkipControl
45
49
  from classiq.interface.model.statement_block import StatementBlock
46
50
  from classiq.interface.model.within_apply_operation import WithinApply
47
51
 
52
+ from classiq.qmod.builtins.functions import H, S
48
53
  from classiq.qmod.generative import is_generative_mode
49
54
  from classiq.qmod.qmod_constant import QConstant
50
55
  from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QScalar, QVar
51
56
  from classiq.qmod.quantum_callable import QCallable
52
57
  from classiq.qmod.quantum_expandable import prepare_arg
58
+ from classiq.qmod.semantics.error_manager import ErrorManager
53
59
  from classiq.qmod.symbolic_expr import SymbolicExpr
54
- from classiq.qmod.utilities import Statements, get_source_ref, suppress_return_value
60
+ from classiq.qmod.utilities import (
61
+ RealFunction,
62
+ Statements,
63
+ get_source_ref,
64
+ qnum_values,
65
+ suppress_return_value,
66
+ )
55
67
 
56
68
  _MISSING_VALUE: Final[int] = -1
57
69
 
70
+ _Params = ParamSpec("_Params")
71
+ _RetType = TypeVar("_RetType")
72
+
73
+
74
+ def qmod_statement(func: Callable[_Params, _RetType]) -> Callable[_Params, _RetType]:
75
+ @wraps(func)
76
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
77
+ source_ref = get_source_ref(sys._getframe(1))
78
+ with ErrorManager().source_ref_context(source_ref):
79
+ return func(*args, **kwargs)
80
+
81
+ return wrapper
82
+
58
83
 
59
84
  @overload
60
85
  def allocate(num_qubits: int | SymbolicExpr, out: Output[QVar]) -> None:
@@ -77,6 +102,7 @@ def allocate(
77
102
 
78
103
 
79
104
  @suppress_return_value
105
+ @qmod_statement
80
106
  def allocate(*args: Any, **kwargs: Any) -> None:
81
107
  """
82
108
  Initialize a quantum variable to a new quantum object in the zero state:
@@ -100,29 +126,34 @@ def allocate(*args: Any, **kwargs: Any) -> None:
100
126
  2. The synthesis engine automatically handles the allocation, either by drawing new qubits from the available pool or by reusing existing ones.
101
127
  """
102
128
  assert QCallable.CURRENT_EXPANDABLE is not None
103
- source_ref = get_source_ref(sys._getframe(1))
129
+ source_ref = get_source_ref(sys._getframe(2))
104
130
  if len(args) == 0:
105
131
  size = kwargs.get("num_qubits", None)
106
132
  is_signed = kwargs.get("is_signed", None)
107
133
  fraction_digits = kwargs.get("fraction_digits", None)
108
- target = kwargs["out"]
134
+ out = kwargs["out"]
109
135
  elif len(args) == 1:
110
136
  if "out" in kwargs:
111
137
  size = args[0]
112
138
  is_signed = kwargs.get("is_signed", None)
113
139
  fraction_digits = kwargs.get("fraction_digits", None)
114
- target = kwargs["out"]
140
+ out = kwargs["out"]
115
141
  else:
116
142
  size = None
117
143
  is_signed = None
118
144
  fraction_digits = None
119
- target = args[0]
145
+ out = args[0]
120
146
  elif len(args) == 2:
121
- size, target = args
147
+ size, out = args
122
148
  is_signed = kwargs.get("is_signed", None)
123
149
  fraction_digits = kwargs.get("fraction_digits", None)
124
150
  else:
125
- size, is_signed, fraction_digits, target = args
151
+ size, is_signed, fraction_digits, out = args
152
+ if not isinstance(out, QVar):
153
+ raise ClassiqValueError(
154
+ f"Argument 'out' of operator 'allocate' must be a quantum variable, got "
155
+ f"{type(out).__name__}"
156
+ )
126
157
  if isinstance(size, QConstant):
127
158
  size.add_to_model()
128
159
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
@@ -134,13 +165,14 @@ def allocate(*args: Any, **kwargs: Any) -> None:
134
165
  if fraction_digits is None
135
166
  else Expression(expr=str(fraction_digits))
136
167
  ),
137
- target=target.get_handle_binding(),
168
+ target=out.get_handle_binding(),
138
169
  source_ref=source_ref,
139
170
  )
140
171
  )
141
172
 
142
173
 
143
174
  @suppress_return_value
175
+ @qmod_statement
144
176
  def bind(
145
177
  source: Input[QVar] | list[Input[QVar]],
146
178
  destination: Output[QVar] | list[Output[QVar]],
@@ -162,7 +194,7 @@ def bind(
162
194
  For more details, see [Qmod Reference](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/bind).
163
195
  """
164
196
  assert QCallable.CURRENT_EXPANDABLE is not None
165
- source_ref = get_source_ref(sys._getframe(1))
197
+ source_ref = get_source_ref(sys._getframe(2))
166
198
  if not isinstance(source, list):
167
199
  source = [source]
168
200
  if not isinstance(destination, list):
@@ -177,6 +209,7 @@ def bind(
177
209
 
178
210
 
179
211
  @suppress_return_value
212
+ @qmod_statement
180
213
  def if_(
181
214
  condition: SymbolicExpr | bool,
182
215
  then: QCallable | Callable[[], Statements],
@@ -198,7 +231,7 @@ def if_(
198
231
  if else_ != _MISSING_VALUE:
199
232
  _validate_operand(else_)
200
233
  assert QCallable.CURRENT_EXPANDABLE is not None
201
- source_ref = get_source_ref(sys._getframe(1))
234
+ source_ref = get_source_ref(sys._getframe(2))
202
235
 
203
236
  if_stmt = ClassicalIf(
204
237
  condition=Expression(expr=str(condition)),
@@ -214,6 +247,7 @@ def if_(
214
247
 
215
248
 
216
249
  @suppress_return_value
250
+ @qmod_statement
217
251
  def control(
218
252
  ctrl: SymbolicExpr | QBit | QArray[QBit] | list[QVar],
219
253
  stmt_block: QCallable | Callable[[], Statements],
@@ -237,7 +271,7 @@ def control(
237
271
  """
238
272
  _validate_operand(stmt_block)
239
273
  assert QCallable.CURRENT_EXPANDABLE is not None
240
- source_ref = get_source_ref(sys._getframe(1))
274
+ source_ref = get_source_ref(sys._getframe(2))
241
275
  control_stmt = Control(
242
276
  expression=Expression(expr=str(ctrl)),
243
277
  body=_operand_to_body(stmt_block, "stmt_block"),
@@ -252,6 +286,7 @@ def control(
252
286
 
253
287
 
254
288
  @suppress_return_value
289
+ @qmod_statement
255
290
  def skip_control(stmt_block: QCallable | Callable[[], Statements]) -> None:
256
291
  """
257
292
  Applies quantum statements unconditionally.
@@ -263,7 +298,7 @@ def skip_control(stmt_block: QCallable | Callable[[], Statements]) -> None:
263
298
  """
264
299
  _validate_operand(stmt_block)
265
300
  assert QCallable.CURRENT_EXPANDABLE is not None
266
- source_ref = get_source_ref(sys._getframe(1))
301
+ source_ref = get_source_ref(sys._getframe(2))
267
302
  sc_stmt = SkipControl(
268
303
  body=_operand_to_body(stmt_block, "stmt_block"),
269
304
  source_ref=source_ref,
@@ -274,6 +309,7 @@ def skip_control(stmt_block: QCallable | Callable[[], Statements]) -> None:
274
309
 
275
310
 
276
311
  @suppress_return_value
312
+ @qmod_statement
277
313
  def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
278
314
  """
279
315
  Initialize a scalar quantum variable using an arithmetic expression.
@@ -287,7 +323,7 @@ def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
287
323
  target_var: An uninitialized scalar quantum variable
288
324
  """
289
325
  assert QCallable.CURRENT_EXPANDABLE is not None
290
- source_ref = get_source_ref(sys._getframe(1))
326
+ source_ref = get_source_ref(sys._getframe(2))
291
327
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
292
328
  ArithmeticOperation(
293
329
  expression=Expression(expr=str(expression)),
@@ -299,6 +335,7 @@ def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
299
335
 
300
336
 
301
337
  @suppress_return_value
338
+ @qmod_statement
302
339
  def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
303
340
  """
304
341
  Perform an amplitude-encoding assignment operation on a quantum variable and a
@@ -311,7 +348,7 @@ def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
311
348
  target_var: A scalar quantum variable
312
349
  """
313
350
  assert QCallable.CURRENT_EXPANDABLE is not None
314
- source_ref = get_source_ref(sys._getframe(1))
351
+ source_ref = get_source_ref(sys._getframe(2))
315
352
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
316
353
  AmplitudeLoadingOperation(
317
354
  expression=Expression(expr=str(expression)),
@@ -322,6 +359,7 @@ def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
322
359
 
323
360
 
324
361
  @suppress_return_value
362
+ @qmod_statement
325
363
  def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
326
364
  """
327
365
  Add an arithmetic expression to a quantum variable.
@@ -333,7 +371,7 @@ def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
333
371
  target_var: A scalar quantum variable
334
372
  """
335
373
  assert QCallable.CURRENT_EXPANDABLE is not None
336
- source_ref = get_source_ref(sys._getframe(1))
374
+ source_ref = get_source_ref(sys._getframe(2))
337
375
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
338
376
  ArithmeticOperation(
339
377
  expression=Expression(expr=str(expression)),
@@ -345,6 +383,7 @@ def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
345
383
 
346
384
 
347
385
  @suppress_return_value
386
+ @qmod_statement
348
387
  def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
349
388
  """
350
389
  Bitwise-XOR a quantum variable with an arithmetic expression.
@@ -356,7 +395,7 @@ def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
356
395
  target_var: A scalar quantum variable
357
396
  """
358
397
  assert QCallable.CURRENT_EXPANDABLE is not None
359
- source_ref = get_source_ref(sys._getframe(1))
398
+ source_ref = get_source_ref(sys._getframe(2))
360
399
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
361
400
  ArithmeticOperation(
362
401
  expression=Expression(expr=str(expression)),
@@ -368,6 +407,7 @@ def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
368
407
 
369
408
 
370
409
  @suppress_return_value
410
+ @qmod_statement
371
411
  def within_apply(
372
412
  within: Callable[[], Statements],
373
413
  apply: Callable[[], Statements],
@@ -387,7 +427,7 @@ def within_apply(
387
427
  _validate_operand(within)
388
428
  _validate_operand(apply)
389
429
  assert QCallable.CURRENT_EXPANDABLE is not None
390
- source_ref = get_source_ref(sys._getframe(1))
430
+ source_ref = get_source_ref(sys._getframe(2))
391
431
  within_apply_stmt = WithinApply(
392
432
  compute=_operand_to_body(within, "within"),
393
433
  action=_operand_to_body(apply, "apply"),
@@ -400,6 +440,7 @@ def within_apply(
400
440
 
401
441
 
402
442
  @suppress_return_value
443
+ @qmod_statement
403
444
  def repeat(count: SymbolicExpr | int, iteration: Callable[[int], Statements]) -> None:
404
445
  """
405
446
  Executes a quantum loop a specified number of times, applying a quantum operation on each iteration.
@@ -426,7 +467,7 @@ def repeat(count: SymbolicExpr | int, iteration: Callable[[int], Statements]) ->
426
467
  """
427
468
  _validate_operand(iteration, num_params=1)
428
469
  assert QCallable.CURRENT_EXPANDABLE is not None
429
- source_ref = get_source_ref(sys._getframe(1))
470
+ source_ref = get_source_ref(sys._getframe(2))
430
471
  iteration_operand = prepare_arg(
431
472
  QuantumOperandDeclaration(
432
473
  name=REPEAT_OPERATOR_NAME,
@@ -455,6 +496,7 @@ def repeat(count: SymbolicExpr | int, iteration: Callable[[int], Statements]) ->
455
496
 
456
497
 
457
498
  @suppress_return_value
499
+ @qmod_statement
458
500
  def power(
459
501
  exponent: SymbolicExpr | int,
460
502
  stmt_block: QCallable | Callable[[], Statements],
@@ -489,7 +531,7 @@ def power(
489
531
  """
490
532
  _validate_operand(stmt_block)
491
533
  assert QCallable.CURRENT_EXPANDABLE is not None
492
- source_ref = get_source_ref(sys._getframe(1))
534
+ source_ref = get_source_ref(sys._getframe(2))
493
535
  power_stmt = Power(
494
536
  power=Expression(expr=str(exponent)),
495
537
  body=_operand_to_body(stmt_block, "stmt_block"),
@@ -501,6 +543,7 @@ def power(
501
543
 
502
544
 
503
545
  @suppress_return_value
546
+ @qmod_statement
504
547
  def invert(stmt_block: QCallable | Callable[[], Statements]) -> None:
505
548
  """
506
549
  Apply the inverse of a quantum gate.
@@ -525,7 +568,7 @@ def invert(stmt_block: QCallable | Callable[[], Statements]) -> None:
525
568
  """
526
569
  _validate_operand(stmt_block)
527
570
  assert QCallable.CURRENT_EXPANDABLE is not None
528
- source_ref = get_source_ref(sys._getframe(1))
571
+ source_ref = get_source_ref(sys._getframe(2))
529
572
  invert_stmt = Invert(
530
573
  body=_operand_to_body(stmt_block, "stmt_block"), source_ref=source_ref
531
574
  )
@@ -535,6 +578,7 @@ def invert(stmt_block: QCallable | Callable[[], Statements]) -> None:
535
578
 
536
579
 
537
580
  @suppress_return_value
581
+ @qmod_statement
538
582
  def phase(
539
583
  phase_expr: SymbolicExpr | float | None = None,
540
584
  theta: SymbolicExpr | float = 1.0,
@@ -557,7 +601,7 @@ def phase(
557
601
  they are equivalent when the phase_expr is a single-qubit variable.
558
602
  """
559
603
  assert QCallable.CURRENT_EXPANDABLE is not None
560
- source_ref = get_source_ref(sys._getframe(1))
604
+ source_ref = get_source_ref(sys._getframe(2))
561
605
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
562
606
  PhaseOperation(
563
607
  expression=Expression(expr=str(phase_expr)),
@@ -568,12 +612,13 @@ def phase(
568
612
 
569
613
 
570
614
  @suppress_return_value
615
+ @qmod_statement
571
616
  def block(
572
617
  statements: QCallable | Callable[[], Statements],
573
618
  ) -> None:
574
619
  _validate_operand(statements)
575
620
  assert QCallable.CURRENT_EXPANDABLE is not None
576
- source_ref = get_source_ref(sys._getframe(1))
621
+ source_ref = get_source_ref(sys._getframe(2))
577
622
 
578
623
  block_stmt = Block(
579
624
  statements=_operand_to_body(statements, "statements"),
@@ -601,13 +646,14 @@ def reset_bounds(
601
646
 
602
647
 
603
648
  @suppress_return_value
649
+ @qmod_statement
604
650
  def reset_bounds(
605
651
  target_var: QNum,
606
652
  lower_bound: float | SymbolicExpr | None = None,
607
653
  upper_bound: float | SymbolicExpr | None = None,
608
654
  ) -> None:
609
655
  assert QCallable.CURRENT_EXPANDABLE is not None
610
- source_ref = get_source_ref(sys._getframe(1))
656
+ source_ref = get_source_ref(sys._getframe(2))
611
657
 
612
658
  lower_bound_expr = (
613
659
  None if lower_bound is None else Expression(expr=str(lower_bound))
@@ -733,10 +779,65 @@ def _operand_to_body(
733
779
  raise ValueError(f"Unexpected operand type: {type(to_operand)}")
734
780
 
735
781
 
782
+ def assign_amplitude_poly_sin(indicator: QBit, expr: Callable, *vars: QNum) -> None:
783
+ """
784
+ Encodes the value of the sine/cosine of a polynomial into the amplitude of the
785
+ respective computational basis state:
786
+ \\( |x_1, x_2, \\ldots, x_n\\rangle|0\\rangle \\rightarrow cos(poly(x_1, x_2, \\ldots, x_n)) + sin(poly(x_1, x_2, \\ldots, x_n))|x_1, x_2, \\ldots, x_n\\rangle|1\\rangle \\)
787
+
788
+ Args:
789
+ indicator: The quantum indicator qubit
790
+ expr: A polynomial function over `len(vars)` QNums
791
+ *vars: Quantum numerics
792
+ """
793
+ phase(-expr(*vars))
794
+ within_apply(
795
+ lambda: H(indicator),
796
+ lambda: control(indicator, lambda: phase(2 * expr(*vars))),
797
+ )
798
+ S(indicator)
799
+
800
+
801
+ def _get_qnum_values(num: QNum) -> list[float]:
802
+ size = num.size
803
+ is_signed = num.is_signed
804
+ fraction_digits = num.fraction_digits
805
+ if (
806
+ not isinstance(size, int)
807
+ or not isinstance(is_signed, bool)
808
+ or not isinstance(fraction_digits, int)
809
+ ):
810
+ raise ClassiqValueError(f"QNum argument {str(num)!r} has symbolic attributes")
811
+
812
+ return qnum_values(size, is_signed, fraction_digits)
813
+
814
+
815
+ def lookup_table(func: RealFunction, targets: QNum | list[QNum]) -> list[float]:
816
+ """
817
+ Reduces a classical function into a lookup table over all the possible values
818
+ of the quantum numbers.
819
+
820
+ Args:
821
+ func: A Python function
822
+ targets: One or more initialized quantum numbers
823
+
824
+ Returns:
825
+ The function's lookup table
826
+
827
+ Notes:
828
+ The QNum arguments must have generative attributes
829
+ """
830
+ if not isinstance(targets, list):
831
+ targets = [targets]
832
+ target_vals = [_get_qnum_values(target) for target in targets]
833
+ return [func(*vals[::-1]) for vals in product(*target_vals[::-1])]
834
+
835
+
736
836
  __all__ = [
737
837
  "allocate",
738
838
  "assign",
739
839
  "assign_amplitude",
840
+ "assign_amplitude_poly_sin",
740
841
  "bind",
741
842
  "block",
742
843
  "control",
@@ -744,6 +845,7 @@ __all__ = [
744
845
  "inplace_add",
745
846
  "inplace_xor",
746
847
  "invert",
848
+ "lookup_table",
747
849
  "phase",
748
850
  "power",
749
851
  "repeat",
@@ -3,6 +3,7 @@ from typing import Union
3
3
 
4
4
  from classiq.interface.exceptions import ClassiqValueError
5
5
  from classiq.interface.generator.types.struct_declaration import StructDeclaration
6
+ from classiq.interface.helpers.datastructures import LenList
6
7
  from classiq.interface.helpers.text_utils import are, readable_list, s
7
8
 
8
9
  from classiq.qmod.builtins.enums import Pauli
@@ -69,13 +70,15 @@ class SparsePauliOp:
69
70
  def __mul__(self, obj: Union[float, "SparsePauliOp"]) -> "SparsePauliOp":
70
71
  if isinstance(obj, (int, float, complex)):
71
72
  return SparsePauliOp(
72
- terms=[
73
- SparsePauliTerm(
74
- paulis=term.paulis,
75
- coefficient=obj * term.coefficient, # type:ignore[arg-type]
76
- )
77
- for term in self.terms
78
- ],
73
+ terms=LenList(
74
+ [
75
+ SparsePauliTerm(
76
+ paulis=term.paulis,
77
+ coefficient=obj * term.coefficient, # type:ignore[arg-type]
78
+ )
79
+ for term in self.terms
80
+ ]
81
+ ),
79
82
  num_qubits=self.num_qubits,
80
83
  )
81
84
  if len(self.terms) != 1 or len(obj.terms) != 1:
@@ -97,14 +100,17 @@ class SparsePauliOp:
97
100
  f"already assigned"
98
101
  )
99
102
  return SparsePauliOp(
100
- terms=[
101
- SparsePauliTerm(
102
- paulis=self.terms[0].paulis
103
- + obj.terms[0].paulis, # type:ignore[arg-type]
104
- coefficient=self.terms[0].coefficient
105
- * obj.terms[0].coefficient, # type:ignore[arg-type]
106
- )
107
- ],
103
+ terms=LenList(
104
+ [
105
+ SparsePauliTerm(
106
+ paulis=LenList( # type:ignore[call-overload]
107
+ self.terms[0].paulis + obj.terms[0].paulis
108
+ ),
109
+ coefficient=self.terms[0].coefficient
110
+ * obj.terms[0].coefficient, # type:ignore[arg-type]
111
+ )
112
+ ]
113
+ ),
108
114
  num_qubits=max(self.num_qubits, obj.num_qubits),
109
115
  )
110
116
 
@@ -113,7 +119,7 @@ class SparsePauliOp:
113
119
 
114
120
  def __add__(self, other: "SparsePauliOp") -> "SparsePauliOp":
115
121
  return SparsePauliOp(
116
- terms=self.terms + other.terms,
122
+ terms=LenList(self.terms + other.terms),
117
123
  num_qubits=max(self.num_qubits, other.num_qubits),
118
124
  )
119
125
 
@@ -156,21 +162,6 @@ class LogNormalModel:
156
162
  sigma: CReal
157
163
 
158
164
 
159
- @dataclass
160
- class QsvmResult:
161
- test_score: CReal
162
- predicted_labels: CArray[CReal]
163
-
164
-
165
- @dataclass
166
- class QSVMFeatureMapPauli:
167
- feature_dimension: CInt
168
- reps: CInt
169
- entanglement: CInt
170
- alpha: CReal
171
- paulis: CArray[CArray[Pauli]]
172
-
173
-
174
165
  BUILTIN_STRUCT_DECLARATIONS = {
175
166
  struct_decl.__name__: StructDeclaration(
176
167
  name=struct_decl.__name__,
@@ -190,8 +181,6 @@ __all__ = [
190
181
  "IndexedPauli",
191
182
  "LogNormalModel",
192
183
  "PauliTerm",
193
- "QSVMFeatureMapPauli",
194
- "QsvmResult",
195
184
  "SparsePauliOp",
196
185
  "SparsePauliTerm",
197
186
  ]
@@ -4,7 +4,7 @@ from typing import Any
4
4
 
5
5
  from classiq.interface.exceptions import ClassiqError
6
6
  from classiq.interface.model.model import Model
7
- from classiq.interface.model.model_visitor import ModelVisitor
7
+ from classiq.interface.model.model_visitor import ModelStatementsVisitor
8
8
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
9
9
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
10
10
  from classiq.interface.model.quantum_function_declaration import (
@@ -47,7 +47,7 @@ def _annotate_function_call_decl(
47
47
  qlambda.set_op_decl(param)
48
48
 
49
49
 
50
- class _CallLambdaAnnotator(ModelVisitor):
50
+ class _CallLambdaAnnotator(ModelStatementsVisitor):
51
51
  def __init__(
52
52
  self, quantum_functions: Mapping[str, QuantumFunctionDeclaration]
53
53
  ) -> None:
@@ -76,7 +76,7 @@ class _CallLambdaAnnotator(ModelVisitor):
76
76
  _annotate_function_call_decl(
77
77
  call, self._quantum_functions | self._current_operands
78
78
  )
79
- self.generic_visit(call)
79
+ self.visit(call.positional_args)
80
80
 
81
81
 
82
82
  def resolve_function_calls(
@@ -1,7 +1,6 @@
1
1
  from collections.abc import Iterator
2
2
  from contextlib import contextmanager
3
3
 
4
- from classiq.interface.ast_node import ASTNode
5
4
  from classiq.interface.exceptions import CLASSIQ_SLACK_COMMUNITY_LINK
6
5
  from classiq.interface.source_reference import SourceReference, SourceReferencedError
7
6
 
@@ -18,14 +17,14 @@ class ErrorManager:
18
17
  self._instantiated = True
19
18
  self._errors: list[SourceReferencedError] = []
20
19
  self._warnings: list[SourceReferencedError] = []
21
- self._current_nodes_stack: list[ASTNode] = []
20
+ self._current_refs_stack: list[SourceReference | None] = []
22
21
  self._call_stack: list[str] = []
23
22
  self._ignore_errors: bool = False
24
23
 
25
24
  @property
26
25
  def _current_source_ref(self) -> SourceReference | None:
27
- if self._current_nodes_stack:
28
- return self._current_nodes_stack[-1].source_ref
26
+ if self._current_refs_stack:
27
+ return self._current_refs_stack[-1]
29
28
  return None
30
29
 
31
30
  @contextmanager
@@ -79,7 +78,7 @@ class ErrorManager:
79
78
  self.clear_warnings()
80
79
 
81
80
  def clear_errors(self) -> None:
82
- self._current_nodes_stack = []
81
+ self._current_refs_stack = []
83
82
  self._errors = []
84
83
 
85
84
  def clear_warnings(self) -> None:
@@ -108,10 +107,10 @@ class ErrorManager:
108
107
  return self._call_stack[-1] if self._call_stack else None
109
108
 
110
109
  @contextmanager
111
- def node_context(self, node: ASTNode) -> Iterator[None]:
112
- self._current_nodes_stack.append(node)
110
+ def source_ref_context(self, ref: SourceReference | None) -> Iterator[None]:
111
+ self._current_refs_stack.append(ref)
113
112
  yield
114
- self._current_nodes_stack.pop()
113
+ self._current_refs_stack.pop()
115
114
 
116
115
  @contextmanager
117
116
  def call(self, func_name: str) -> Iterator[None]:
classiq/qmod/utilities.py CHANGED
@@ -3,7 +3,6 @@ import inspect
3
3
  import itertools
4
4
  import keyword
5
5
  import sys
6
- from collections import Counter
7
6
  from collections.abc import Callable, Iterable
8
7
  from enum import Enum as PythonEnum
9
8
  from types import FrameType
@@ -195,13 +194,4 @@ def qnum_attributes(max_size: int) -> list[tuple[int, bool, int]]:
195
194
  ]
196
195
 
197
196
 
198
- _VAR_NAME_COUNTER: Counter[str] = Counter()
199
-
200
-
201
- def get_temp_var_name(var_name: str = "temp") -> str:
202
- n = _VAR_NAME_COUNTER[var_name]
203
- _VAR_NAME_COUNTER[var_name] += 1
204
- return f"{var_name}_{n}"
205
-
206
-
207
197
  RealFunction = Callable[Params, float]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: classiq
3
- Version: 0.94.2
3
+ Version: 0.96.0
4
4
  Summary: Classiq's Python SDK for quantum computing
5
5
  Keywords: quantum computing,quantum circuits,quantum algorithms,QAD,QDL
6
6
  Author: Classiq Technologies