classiq 0.46.1__py3-none-any.whl → 0.48.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 (71) hide show
  1. classiq/_internals/api_wrapper.py +45 -8
  2. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +2 -7
  3. classiq/applications/grover/grover_model_constructor.py +2 -1
  4. classiq/execution/execution_session.py +133 -45
  5. classiq/execution/jobs.py +120 -1
  6. classiq/interface/_version.py +1 -1
  7. classiq/interface/backend/quantum_backend_providers.py +0 -1
  8. classiq/interface/debug_info/debug_info.py +23 -1
  9. classiq/interface/execution/primitives.py +17 -0
  10. classiq/interface/executor/iqae_result.py +3 -3
  11. classiq/interface/executor/result.py +3 -1
  12. classiq/interface/generator/arith/arithmetic_operations.py +5 -2
  13. classiq/interface/generator/arith/binary_ops.py +21 -14
  14. classiq/interface/generator/arith/extremum_operations.py +9 -1
  15. classiq/interface/generator/arith/number_utils.py +6 -0
  16. classiq/interface/generator/arith/register_user_input.py +30 -21
  17. classiq/interface/generator/arith/unary_ops.py +13 -1
  18. classiq/interface/generator/expressions/expression.py +8 -0
  19. classiq/interface/generator/functions/type_name.py +1 -3
  20. classiq/interface/generator/generated_circuit_data.py +47 -2
  21. classiq/interface/generator/quantum_program.py +10 -2
  22. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +17 -3
  23. classiq/interface/ide/visual_model.py +10 -5
  24. classiq/interface/interface_version.py +1 -1
  25. classiq/interface/model/bind_operation.py +0 -3
  26. classiq/interface/model/phase_operation.py +11 -0
  27. classiq/interface/model/port_declaration.py +1 -12
  28. classiq/interface/model/quantum_expressions/arithmetic_operation.py +34 -6
  29. classiq/interface/model/quantum_lambda_function.py +4 -1
  30. classiq/interface/model/quantum_statement.py +16 -1
  31. classiq/interface/model/quantum_variable_declaration.py +0 -22
  32. classiq/interface/model/statement_block.py +3 -0
  33. classiq/interface/server/global_versions.py +4 -4
  34. classiq/interface/server/routes.py +0 -3
  35. classiq/model_expansions/capturing/propagated_var_stack.py +5 -2
  36. classiq/model_expansions/closure.py +7 -2
  37. classiq/model_expansions/evaluators/quantum_type_utils.py +0 -7
  38. classiq/model_expansions/generative_functions.py +146 -28
  39. classiq/model_expansions/interpreter.py +17 -5
  40. classiq/model_expansions/quantum_operations/classicalif.py +27 -10
  41. classiq/model_expansions/quantum_operations/control.py +22 -15
  42. classiq/model_expansions/quantum_operations/emitter.py +68 -7
  43. classiq/model_expansions/quantum_operations/expression_operation.py +25 -16
  44. classiq/model_expansions/quantum_operations/inplace_binary_operation.py +167 -95
  45. classiq/model_expansions/quantum_operations/invert.py +12 -6
  46. classiq/model_expansions/quantum_operations/phase.py +189 -0
  47. classiq/model_expansions/quantum_operations/power.py +9 -8
  48. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +20 -5
  49. classiq/model_expansions/quantum_operations/quantum_function_call.py +1 -1
  50. classiq/model_expansions/quantum_operations/repeat.py +32 -13
  51. classiq/model_expansions/quantum_operations/within_apply.py +19 -6
  52. classiq/model_expansions/scope.py +16 -5
  53. classiq/model_expansions/scope_initialization.py +11 -1
  54. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +23 -1
  55. classiq/model_expansions/visitors/variable_references.py +11 -7
  56. classiq/qmod/builtins/__init__.py +10 -0
  57. classiq/qmod/builtins/constants.py +10 -0
  58. classiq/qmod/builtins/functions/state_preparation.py +4 -1
  59. classiq/qmod/builtins/operations.py +55 -161
  60. classiq/qmod/create_model_function.py +1 -1
  61. classiq/qmod/generative.py +14 -5
  62. classiq/qmod/native/pretty_printer.py +14 -4
  63. classiq/qmod/pretty_print/pretty_printer.py +14 -4
  64. classiq/qmod/qmod_constant.py +28 -18
  65. classiq/qmod/qmod_variable.py +43 -23
  66. classiq/qmod/quantum_expandable.py +14 -1
  67. classiq/qmod/semantics/static_semantics_visitor.py +10 -0
  68. classiq/qmod/semantics/validation/constants_validation.py +16 -0
  69. {classiq-0.46.1.dist-info → classiq-0.48.0.dist-info}/METADATA +9 -4
  70. {classiq-0.46.1.dist-info → classiq-0.48.0.dist-info}/RECORD +71 -66
  71. {classiq-0.46.1.dist-info → classiq-0.48.0.dist-info}/WHEEL +0 -0
@@ -48,6 +48,7 @@ from classiq.interface.model.quantum_expressions.amplitude_loading_operation imp
48
48
  )
49
49
  from classiq.interface.model.quantum_expressions.arithmetic_operation import (
50
50
  ArithmeticOperation,
51
+ ArithmeticOperationKind,
51
52
  )
52
53
  from classiq.interface.model.quantum_type import (
53
54
  QuantumBit,
@@ -57,10 +58,10 @@ from classiq.interface.model.quantum_type import (
57
58
  )
58
59
  from classiq.interface.source_reference import SourceReference
59
60
 
60
- from classiq.qmod.cparam import ArrayBase, CBool, CInt, CParamScalar
61
+ from classiq.qmod.cparam import ArrayBase, CInt, CParamScalar
61
62
  from classiq.qmod.generative import (
62
63
  generative_mode_context,
63
- get_frontend_interpreter,
64
+ interpret_expression,
64
65
  is_generative_mode,
65
66
  )
66
67
  from classiq.qmod.model_state_container import QMODULE, ModelStateContainer
@@ -95,10 +96,6 @@ def _no_current_expandable() -> Iterator[None]:
95
96
  QCallable.CURRENT_EXPANDABLE = current_expandable
96
97
 
97
98
 
98
- def _evaluate_expression(expr: str) -> Any:
99
- return get_frontend_interpreter().evaluate(Expression(expr=expr)).value
100
-
101
-
102
99
  class QVar(Symbolic):
103
100
  def __init__(
104
101
  self,
@@ -171,7 +168,7 @@ class QVar(Symbolic):
171
168
  def size(self) -> Union[CParamScalar, int]:
172
169
  if is_generative_mode():
173
170
  with generative_mode_context(False):
174
- return _evaluate_expression(str(self.size))
171
+ return interpret_expression(str(self.size))
175
172
  return CParamScalar(f"get_field({self}, 'size')")
176
173
 
177
174
 
@@ -192,7 +189,10 @@ class QScalar(QVar, SymbolicExpr):
192
189
  SymbolicExpr.__init__(self, str(origin), True)
193
190
 
194
191
  def _insert_arith_operation(
195
- self, expr: SymbolicTypes, inplace: bool, source_ref: SourceReference
192
+ self,
193
+ expr: SymbolicTypes,
194
+ kind: ArithmeticOperationKind,
195
+ source_ref: SourceReference,
196
196
  ) -> None:
197
197
  # Fixme: Arithmetic operations are not yet supported on slices (see CAD-12670)
198
198
  if TYPE_CHECKING:
@@ -201,7 +201,7 @@ class QScalar(QVar, SymbolicExpr):
201
201
  ArithmeticOperation(
202
202
  expression=Expression(expr=str(expr)),
203
203
  result_var=self.get_handle_binding(),
204
- inplace_result=inplace,
204
+ operation_kind=kind,
205
205
  source_ref=source_ref,
206
206
  )
207
207
  )
@@ -225,7 +225,9 @@ class QScalar(QVar, SymbolicExpr):
225
225
  f"Invalid argument {other!r} for out-of-place arithmetic operation"
226
226
  )
227
227
 
228
- self._insert_arith_operation(other, False, get_source_ref(sys._getframe(1)))
228
+ self._insert_arith_operation(
229
+ other, ArithmeticOperationKind.Assignment, get_source_ref(sys._getframe(1))
230
+ )
229
231
  return self
230
232
 
231
233
  def __ixor__(self, other: Any) -> Self:
@@ -234,7 +236,20 @@ class QScalar(QVar, SymbolicExpr):
234
236
  f"Invalid argument {other!r} for in-place arithmetic operation"
235
237
  )
236
238
 
237
- self._insert_arith_operation(other, True, get_source_ref(sys._getframe(1)))
239
+ self._insert_arith_operation(
240
+ other, ArithmeticOperationKind.InplaceXor, get_source_ref(sys._getframe(1))
241
+ )
242
+ return self
243
+
244
+ def __iadd__(self, other: Any) -> Self:
245
+ if not isinstance(other, get_args(SymbolicTypes)):
246
+ raise TypeError(
247
+ f"Invalid argument {other!r} for in-place arithmetic operation"
248
+ )
249
+
250
+ self._insert_arith_operation(
251
+ other, ArithmeticOperationKind.InplaceAdd, get_source_ref(sys._getframe(1))
252
+ )
238
253
  return self
239
254
 
240
255
  def __imul__(self, other: Any) -> Self:
@@ -273,18 +288,21 @@ class QNum(Generic[_P], QScalar):
273
288
  self,
274
289
  name: Union[str, HandleBinding],
275
290
  size: Union[int, CInt, Expression, None] = None,
276
- is_signed: Union[bool, CBool, Expression, None] = None,
291
+ is_signed: Union[bool, Expression, SymbolicExpr, None] = None,
277
292
  fraction_digits: Union[int, CInt, Expression, None] = None,
278
293
  _expr_str: Optional[str] = None,
279
294
  ):
280
- if (
281
- size is None
282
- and (is_signed is not None or fraction_digits is not None)
283
- or size is not None
284
- and (is_signed is None or fraction_digits is None)
285
- ):
295
+ if size is None and (is_signed is not None or fraction_digits is not None):
286
296
  raise ClassiqValueError(
287
- "Assign none or all of size, is_signed, and fraction_digits"
297
+ "Cannot assign 'is_signed' and 'fraction_digits' without 'size'"
298
+ )
299
+ if is_signed is not None and fraction_digits is None:
300
+ raise ClassiqValueError(
301
+ "Cannot assign 'is_signed' without 'fraction_digits'"
302
+ )
303
+ if is_signed is None and fraction_digits is not None:
304
+ raise ClassiqValueError(
305
+ "Cannot assign 'fraction_digits' without 'is_signed'"
288
306
  )
289
307
  self._size = (
290
308
  size
@@ -308,11 +326,13 @@ class QNum(Generic[_P], QScalar):
308
326
  type_args = version_portable_get_args(type_hint)
309
327
  if len(type_args) == 0:
310
328
  return None, None, None
311
- if len(type_args) != 3:
329
+ if len(type_args) not in (1, 3):
312
330
  raise ClassiqValueError(
313
331
  "QNum receives three type arguments: QNum[size: int | CInt, "
314
332
  "is_signed: bool | CBool, fraction_digits: int | CInt]"
315
333
  )
334
+ if len(type_args) == 1:
335
+ return type_args[0], None, None
316
336
  return type_args[0], type_args[1], type_args[2]
317
337
 
318
338
  @classmethod
@@ -354,14 +374,14 @@ class QNum(Generic[_P], QScalar):
354
374
  def fraction_digits(self) -> Union[CParamScalar, int]:
355
375
  if is_generative_mode():
356
376
  with generative_mode_context(False):
357
- return _evaluate_expression(str(self.fraction_digits))
377
+ return interpret_expression(str(self.fraction_digits))
358
378
  return CParamScalar(f"get_field({self}, 'fraction_digits')")
359
379
 
360
380
  @property
361
381
  def is_signed(self) -> Union[CParamScalar, bool]:
362
382
  if is_generative_mode():
363
383
  with generative_mode_context(False):
364
- return _evaluate_expression(str(self.is_signed))
384
+ return interpret_expression(str(self.is_signed))
365
385
  return CParamScalar(f"get_field({self}, 'is_signed')")
366
386
 
367
387
  # Support comma-separated generic args in older Python versions
@@ -466,7 +486,7 @@ class QArray(ArrayBase[_P], QVar):
466
486
  def len(self) -> Union[CParamScalar, int]:
467
487
  if is_generative_mode():
468
488
  with generative_mode_context(False):
469
- return _evaluate_expression(str(self.len))
489
+ return interpret_expression(str(self.len))
470
490
  if self._length is not None:
471
491
  return CParamScalar(f"{self._length}")
472
492
  return CParamScalar(f"get_field({self}, 'len')")
@@ -122,8 +122,17 @@ class QExpandable(QCallable, QExpandableInterface, ABC):
122
122
 
123
123
  def _get_positional_args(self) -> List[ArgType]:
124
124
  result: List[ArgType] = []
125
+ rename_params = self.infer_rename_params()
126
+ if rename_params is not None and len(rename_params) != len(
127
+ self.func_decl.positional_arg_declarations
128
+ ):
129
+ op_name = (
130
+ f" {self.func_decl.name!r}" if self.func_decl.name is not None else ""
131
+ )
132
+ raise ClassiqValueError(
133
+ f"Operand{op_name} takes {len(self.func_decl.positional_arg_declarations)} arguments but the received function takes {len(rename_params)} argument"
134
+ )
125
135
  for idx, arg in enumerate(self.func_decl.positional_arg_declarations):
126
- rename_params = self.infer_rename_params()
127
136
  actual_name = (
128
137
  rename_params[idx] if rename_params is not None else arg.get_name()
129
138
  )
@@ -303,6 +312,10 @@ def prepare_arg(
303
312
  return [prepare_arg(arg_decl, v, func_name, param_name) for v in val]
304
313
 
305
314
  if not isinstance(val, QCallable):
315
+ if not callable(val):
316
+ raise ClassiqValueError(
317
+ f"Operand argument to {param_name!r} must be a callable object"
318
+ )
306
319
  new_arg_decl = decl_without_type_attributes(arg_decl)
307
320
  val = QLambdaFunction(new_arg_decl, val)
308
321
  val.expand()
@@ -51,6 +51,9 @@ from classiq.interface.model.within_apply_operation import WithinApply
51
51
  from classiq.qmod.builtins.functions import BUILTIN_FUNCTION_DECLARATIONS
52
52
  from classiq.qmod.semantics.annotation import annotate_function_call_decl
53
53
  from classiq.qmod.semantics.error_manager import ErrorManager
54
+ from classiq.qmod.semantics.validation.constants_validation import (
55
+ check_duplicate_constants,
56
+ )
54
57
  from classiq.qmod.semantics.validation.func_call_validation import (
55
58
  check_no_overlapping_quantum_args,
56
59
  validate_call_arguments,
@@ -110,6 +113,7 @@ class StaticSemanticsVisitor(Visitor):
110
113
 
111
114
  def visit_Model(self, model: Model) -> None:
112
115
  check_duplicate_types([*model.enums, *model.types, *model.qstructs])
116
+ check_duplicate_constants(model.constants)
113
117
  for qstruct in model.qstructs:
114
118
  check_qstruct_has_fields(qstruct)
115
119
  if check_qstruct_fields_are_defined(
@@ -318,6 +322,12 @@ class StaticSemanticsVisitor(Visitor):
318
322
 
319
323
  for handle_metadata in inouts:
320
324
  handle_binding = handle_metadata.handle
325
+
326
+ if handle_binding.name not in self.current_scope.variable_states:
327
+ ErrorManager().add_error(
328
+ f"Variable {handle_binding.name!r} is not defined"
329
+ )
330
+ return
321
331
  handle_wiring_state = self.current_scope.variable_states[
322
332
  handle_binding.name
323
333
  ]
@@ -0,0 +1,16 @@
1
+ from typing import Sequence
2
+
3
+ from classiq.interface.generator.constant import Constant
4
+
5
+ from classiq.qmod.builtins import BUILTIN_CONSTANTS
6
+ from classiq.qmod.semantics.error_manager import ErrorManager
7
+
8
+
9
+ def check_duplicate_constants(constants: Sequence[Constant]) -> None:
10
+ known_constants = {constant.name: constant for constant in BUILTIN_CONSTANTS}
11
+ for constant in constants:
12
+ if constant.name in known_constants:
13
+ with ErrorManager().node_context(constant):
14
+ ErrorManager().add_error(f"Constant {constant.name!r} already exists")
15
+ else:
16
+ known_constants[constant.name] = constant
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: classiq
3
- Version: 0.46.1
3
+ Version: 0.48.0
4
4
  Summary: Classiq's Python SDK for quantum computing
5
5
  Home-page: https://classiq.io
6
6
  License: Proprietary
7
7
  Keywords: quantum computing,quantum circuits,quantum algorithms,QAD,QDL
8
8
  Author: Classiq Technologies
9
9
  Author-email: support@classiq.io
10
- Requires-Python: >=3.8,<3.12
10
+ Requires-Python: >=3.8,<3.13
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: Intended Audience :: Education
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.8
20
20
  Classifier: Programming Language :: Python :: 3.9
21
21
  Classifier: Programming Language :: Python :: 3.10
22
22
  Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
23
24
  Classifier: Programming Language :: Python :: 3 :: Only
24
25
  Classifier: Topic :: Scientific/Engineering
25
26
  Classifier: Topic :: Software Development
@@ -34,16 +35,20 @@ Requires-Dist: Pyomo (>=6.5,<6.6)
34
35
  Requires-Dist: black (>=24.0,<25.0)
35
36
  Requires-Dist: httpx (>=0.23.0,<1)
36
37
  Requires-Dist: ipywidgets (>=7.7.1,<8.0.0) ; extra == "analyzer-sdk"
38
+ Requires-Dist: jupyterlab (>=4.2.5,<5.0.0) ; extra == "analyzer-sdk"
37
39
  Requires-Dist: keyring (>=23.5.0,<24.0.0)
38
40
  Requires-Dist: matplotlib (>=3.4.3,<4.0.0)
39
41
  Requires-Dist: networkx (>=2.5.1,<3.0.0)
42
+ Requires-Dist: notebook (>=7.2.2,<8.0.0) ; extra == "analyzer-sdk"
40
43
  Requires-Dist: numexpr (>=2.7.3,<3.0.0)
41
- Requires-Dist: numpy (>=1.20.1,<2.0.0)
44
+ Requires-Dist: numpy (>=1.20.1,<2.0.0) ; python_version < "3.12"
45
+ Requires-Dist: numpy (>=1.26.0,<2.0.0) ; python_version >= "3.12"
42
46
  Requires-Dist: packaging (>=23.2,<24.0)
43
47
  Requires-Dist: pandas (>=1.4.0,<3.0.0)
44
48
  Requires-Dist: plotly (>=5.7.0,<6.0.0)
45
49
  Requires-Dist: pydantic (>=1.9.1,<2.0.0)
46
- Requires-Dist: scipy (>=1.10.1,<2.0.0)
50
+ Requires-Dist: scipy (>=1.10.0,<2.0.0) ; python_version < "3.12"
51
+ Requires-Dist: scipy (>=1.11.0,<2.0.0) ; python_version >= "3.12"
47
52
  Requires-Dist: sympy (>=1.13.0,<2.0.0)
48
53
  Requires-Dist: tabulate (>=0.8.9,<1)
49
54
  Requires-Dist: torch (>=2.0,<3.0) ; extra == "qml"