classiq 0.60.0__py3-none-any.whl → 0.61.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 (98) hide show
  1. classiq/__init__.py +2 -0
  2. classiq/_internals/client.py +28 -1
  3. classiq/applications/__init__.py +1 -1
  4. classiq/applications/chemistry/__init__.py +7 -7
  5. classiq/applications/chemistry/chemistry_model_constructor.py +17 -6
  6. classiq/applications/combinatorial_optimization/__init__.py +7 -1
  7. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -0
  8. classiq/applications/combinatorial_optimization/combinatorial_problem.py +197 -0
  9. classiq/applications/finance/finance_model_constructor.py +6 -6
  10. classiq/applications/grover/grover_model_constructor.py +3 -0
  11. classiq/applications/libraries/qmci_library.py +1 -10
  12. classiq/applications/qnn/__init__.py +1 -1
  13. classiq/applications/qnn/datasets/__init__.py +8 -8
  14. classiq/applications/qsvm/qsvm.py +1 -1
  15. classiq/execution/__init__.py +0 -2
  16. classiq/execution/execution_session.py +6 -0
  17. classiq/executor.py +1 -1
  18. classiq/interface/_version.py +1 -1
  19. classiq/interface/backend/backend_preferences.py +12 -12
  20. classiq/interface/executor/execution_preferences.py +1 -1
  21. classiq/interface/generator/application_apis/chemistry_declarations.py +1 -1
  22. classiq/interface/generator/application_apis/finance_declarations.py +2 -2
  23. classiq/interface/generator/arith/arithmetic.py +16 -1
  24. classiq/interface/generator/arith/arithmetic_expression_validator.py +4 -3
  25. classiq/interface/generator/expressions/expression_constants.py +3 -0
  26. classiq/interface/generator/generated_circuit_data.py +58 -20
  27. classiq/interface/generator/model/__init__.py +1 -1
  28. classiq/interface/generator/model/quantum_register.py +3 -3
  29. classiq/interface/generator/standard_gates/controlled_standard_gates.py +20 -32
  30. classiq/interface/ide/visual_model.py +1 -0
  31. classiq/interface/interface_version.py +1 -1
  32. classiq/interface/model/model.py +2 -3
  33. classiq/interface/model/quantum_function_call.py +4 -7
  34. classiq/interface/model/quantum_function_declaration.py +7 -0
  35. classiq/interface/model/quantum_lambda_function.py +10 -1
  36. classiq/interface/model/quantum_type.py +3 -1
  37. classiq/model_expansions/atomic_expression_functions_defs.py +3 -1
  38. classiq/model_expansions/capturing/captured_vars.py +24 -8
  39. classiq/model_expansions/capturing/mangling_utils.py +23 -15
  40. classiq/model_expansions/evaluators/arg_type_match.py +7 -7
  41. classiq/model_expansions/expression_evaluator.py +5 -2
  42. classiq/model_expansions/function_builder.py +21 -4
  43. classiq/model_expansions/generative_functions.py +12 -90
  44. classiq/model_expansions/interpreter.py +58 -11
  45. classiq/model_expansions/quantum_operations/call_emitter.py +19 -10
  46. classiq/model_expansions/quantum_operations/classicalif.py +1 -1
  47. classiq/model_expansions/quantum_operations/control.py +5 -31
  48. classiq/model_expansions/quantum_operations/emitter.py +27 -14
  49. classiq/model_expansions/quantum_operations/expression_operation.py +3 -5
  50. classiq/model_expansions/quantum_operations/inplace_binary_operation.py +57 -15
  51. classiq/model_expansions/quantum_operations/invert.py +1 -6
  52. classiq/model_expansions/quantum_operations/phase.py +2 -5
  53. classiq/model_expansions/quantum_operations/power.py +0 -4
  54. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +19 -30
  55. classiq/model_expansions/quantum_operations/quantum_function_call.py +3 -1
  56. classiq/model_expansions/quantum_operations/shallow_emitter.py +155 -0
  57. classiq/model_expansions/quantum_operations/within_apply.py +0 -14
  58. classiq/model_expansions/scope.py +10 -4
  59. classiq/model_expansions/scope_initialization.py +0 -11
  60. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +7 -0
  61. classiq/model_expansions/sympy_conversion/sympy_to_python.py +12 -2
  62. classiq/model_expansions/transformers/ast_renamer.py +26 -0
  63. classiq/model_expansions/transformers/var_splitter.py +11 -12
  64. classiq/model_expansions/visitors/variable_references.py +20 -12
  65. classiq/qmod/builtins/classical_execution_primitives.py +6 -6
  66. classiq/qmod/builtins/classical_functions.py +10 -10
  67. classiq/qmod/builtins/functions/__init__.py +89 -103
  68. classiq/qmod/builtins/functions/amplitude_estimation.py +1 -1
  69. classiq/qmod/builtins/functions/arithmetic.py +1 -1
  70. classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +6 -6
  71. classiq/qmod/builtins/functions/grover.py +5 -5
  72. classiq/qmod/builtins/functions/hea.py +1 -1
  73. classiq/qmod/builtins/functions/linear_pauli_rotation.py +2 -2
  74. classiq/qmod/builtins/functions/modular_exponentiation.py +8 -8
  75. classiq/qmod/builtins/functions/operators.py +1 -1
  76. classiq/qmod/builtins/functions/qaoa_penalty.py +5 -5
  77. classiq/qmod/builtins/functions/qft_functions.py +2 -2
  78. classiq/qmod/builtins/functions/qpe.py +9 -12
  79. classiq/qmod/builtins/functions/qsvt.py +177 -15
  80. classiq/qmod/builtins/functions/state_preparation.py +9 -9
  81. classiq/qmod/builtins/functions/swap_test.py +1 -1
  82. classiq/qmod/builtins/functions/utility_functions.py +2 -2
  83. classiq/qmod/builtins/functions/variational.py +2 -2
  84. classiq/qmod/builtins/operations.py +3 -3
  85. classiq/qmod/builtins/structs.py +9 -9
  86. classiq/qmod/native/pretty_printer.py +17 -19
  87. classiq/qmod/pretty_print/pretty_printer.py +9 -6
  88. classiq/qmod/qmod_variable.py +2 -5
  89. classiq/qmod/quantum_expandable.py +18 -4
  90. classiq/qmod/quantum_function.py +19 -6
  91. classiq/qmod/semantics/static_semantics_visitor.py +34 -16
  92. classiq/qmod/semantics/validation/func_call_validation.py +9 -5
  93. classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
  94. classiq/qmod/symbolic.py +47 -47
  95. {classiq-0.60.0.dist-info → classiq-0.61.0.dist-info}/METADATA +1 -1
  96. {classiq-0.60.0.dist-info → classiq-0.61.0.dist-info}/RECORD +97 -94
  97. classiq/execution/qaoa.py +0 -86
  98. {classiq-0.60.0.dist-info → classiq-0.61.0.dist-info}/WHEEL +0 -0
@@ -452,11 +452,8 @@ class QArray(ArrayBase[_P], QVar):
452
452
  )
453
453
  if self._length is not None and self._length.is_evaluated():
454
454
  length = self._length.to_int_value()
455
- if (
456
- isinstance(slice_.start, int)
457
- and slice_.start < 0
458
- or isinstance(slice_.stop, int)
459
- and slice_.stop > length
455
+ if (isinstance(slice_.start, int) and slice_.start < 0) or (
456
+ isinstance(slice_.stop, int) and slice_.stop > length
460
457
  ):
461
458
  raise ClassiqValueError(SLICE_OUT_OF_BOUNDS_MSG)
462
459
 
@@ -18,7 +18,7 @@ import pydantic
18
18
  from sympy import Basic
19
19
  from typing_extensions import Self
20
20
 
21
- from classiq.interface.exceptions import ClassiqValueError
21
+ from classiq.interface.exceptions import ClassiqInternalError, ClassiqValueError
22
22
  from classiq.interface.generator.expressions.expression import Expression
23
23
  from classiq.interface.generator.functions.concrete_types import (
24
24
  NativePythonClassicalTypes,
@@ -30,7 +30,6 @@ from classiq.interface.model.classical_parameter_declaration import (
30
30
  from classiq.interface.model.port_declaration import AnonPortDeclaration
31
31
  from classiq.interface.model.quantum_function_call import (
32
32
  ArgValue,
33
- OperandIdentifier,
34
33
  QuantumFunctionCall,
35
34
  )
36
35
  from classiq.interface.model.quantum_function_declaration import (
@@ -39,7 +38,11 @@ from classiq.interface.model.quantum_function_declaration import (
39
38
  AnonQuantumOperandDeclaration,
40
39
  QuantumFunctionDeclaration,
41
40
  )
42
- from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
41
+ from classiq.interface.model.quantum_lambda_function import (
42
+ OperandIdentifier,
43
+ QuantumCallable,
44
+ QuantumLambdaFunction,
45
+ )
43
46
  from classiq.interface.model.quantum_statement import QuantumStatement
44
47
  from classiq.interface.model.quantum_type import QuantumType
45
48
  from classiq.interface.model.variable_declaration_statement import (
@@ -232,7 +235,9 @@ class QTerminalCallable(QCallable):
232
235
  raise NotImplementedError("Operand lists don't support slicing")
233
236
  if isinstance(key, CParam) and not isinstance(key, CParamScalar):
234
237
  raise ClassiqValueError("Non-classical parameter for slicing")
235
- return QTerminalCallable(self._decl, index_=key)
238
+ if not isinstance(self._decl, AnonQuantumOperandDeclaration):
239
+ raise ClassiqInternalError
240
+ return QTerminalCallable(self._decl.element_declaration, index_=key)
236
241
 
237
242
  def __len__(self) -> int:
238
243
  raise ClassiqValueError(
@@ -267,6 +272,13 @@ class QTerminalCallable(QCallable):
267
272
  self.func_decl, self._index, source_ref_, *args, **kwargs
268
273
  )
269
274
 
275
+ def get_arg(self) -> QuantumCallable:
276
+ if self._index is None:
277
+ return self._decl.name
278
+ return OperandIdentifier(
279
+ name=self._decl.name, index=Expression(expr=str(self._index))
280
+ )
281
+
270
282
 
271
283
  @overload
272
284
  def prepare_arg(
@@ -329,6 +341,8 @@ def prepare_arg(
329
341
 
330
342
  if isinstance(val, QExpandable):
331
343
  val.expand()
344
+ elif isinstance(val, QTerminalCallable):
345
+ return val.get_arg()
332
346
  return val.func_decl.name
333
347
 
334
348
 
@@ -76,6 +76,18 @@ class QFunc(BaseQFunc):
76
76
  functools.update_wrapper(self, py_callable)
77
77
  self.compilation_metadata: Optional[CompilationMetadata] = None
78
78
 
79
+ @property
80
+ def pure_decl(self) -> NamedParamsQuantumFunctionDeclaration:
81
+ if type(self.func_decl) is NamedParamsQuantumFunctionDeclaration:
82
+ return self.func_decl
83
+ return NamedParamsQuantumFunctionDeclaration(
84
+ **{
85
+ k: v
86
+ for k, v in self.func_decl.model_dump().items()
87
+ if k in NamedParamsQuantumFunctionDeclaration.model_fields
88
+ }
89
+ )
90
+
79
91
  @property
80
92
  def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
81
93
  return self._qmodule.native_defs.get(
@@ -181,6 +193,10 @@ class ExternalQFunc(QTerminalCallable):
181
193
  def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
182
194
  return self._decl
183
195
 
196
+ @property
197
+ def pure_decl(self) -> NamedParamsQuantumFunctionDeclaration:
198
+ return self.func_decl
199
+
184
200
  def get_implementation(self) -> NativeFunctionDefinition:
185
201
  model = QFunc(self._py_callable).create_model()
186
202
  return [
@@ -224,12 +240,9 @@ def _validate_no_gen_params(annotations: dict[str, Any]) -> None:
224
240
  for name, annotation in annotations.items()
225
241
  if not (
226
242
  name == "return"
227
- or isclass(annotation)
228
- and issubclass(annotation, CParam)
229
- or isclass(annotation)
230
- and is_dataclass(annotation)
231
- or isclass(annotation)
232
- and isinstance(annotation, EnumMeta)
243
+ or (isclass(annotation) and issubclass(annotation, CParam))
244
+ or (isclass(annotation) and is_dataclass(annotation))
245
+ or (isclass(annotation) and isinstance(annotation, EnumMeta))
233
246
  or get_origin(annotation) is CArray
234
247
  or (get_origin(annotation) or annotation) is QCallable
235
248
  or (get_origin(annotation) or annotation) is QCallableList
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  from collections.abc import Iterator, Mapping, Sequence
2
3
  from contextlib import contextmanager
3
4
  from typing import (
@@ -6,7 +7,9 @@ from typing import (
6
7
  )
7
8
 
8
9
  from classiq.interface.exceptions import ClassiqSemanticError
10
+ from classiq.interface.generator.expressions.expression import Expression
9
11
  from classiq.interface.generator.function_params import PortDirection
12
+ from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
10
13
  from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
11
14
  from classiq.interface.generator.functions.port_declaration import (
12
15
  PortDeclarationDirection,
@@ -25,6 +28,9 @@ from classiq.interface.model.inplace_binary_operation import InplaceBinaryOperat
25
28
  from classiq.interface.model.model import Model
26
29
  from classiq.interface.model.native_function_definition import NativeFunctionDefinition
27
30
  from classiq.interface.model.port_declaration import PortDeclaration
31
+ from classiq.interface.model.quantum_expressions.quantum_expression import (
32
+ QuantumExpressionOperation,
33
+ )
28
34
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
29
35
  from classiq.interface.model.quantum_function_declaration import (
30
36
  AnonQuantumOperandDeclaration,
@@ -41,7 +47,10 @@ from classiq.interface.model.variable_declaration_statement import (
41
47
  )
42
48
  from classiq.interface.model.within_apply_operation import WithinApply
43
49
 
44
- from classiq.qmod.builtins.functions import BUILTIN_FUNCTION_DECLARATIONS
50
+ from classiq.model_expansions.visitors.variable_references import VarRefCollector
51
+ from classiq.qmod.builtins.functions import (
52
+ BUILTIN_FUNCTION_DECLARATIONS,
53
+ )
45
54
  from classiq.qmod.semantics.annotation import annotate_function_call_decl
46
55
  from classiq.qmod.semantics.error_manager import ErrorManager
47
56
  from classiq.qmod.semantics.qstruct_annotator import QStructAnnotator
@@ -52,6 +61,9 @@ from classiq.qmod.semantics.validation.func_call_validation import (
52
61
  check_no_overlapping_quantum_args,
53
62
  validate_call_arguments,
54
63
  )
64
+ from classiq.qmod.semantics.validation.function_name_collisions_validation import (
65
+ _check_function_name_collisions,
66
+ )
55
67
  from classiq.qmod.semantics.validation.handle_validation import resolve_handle
56
68
  from classiq.qmod.semantics.validation.main_validation import validate_main_function
57
69
  from classiq.qmod.semantics.validation.types_validation import (
@@ -266,6 +278,26 @@ class StaticSemanticsVisitor(Visitor):
266
278
  def visit_HandleBinding(self, handle: HandleBinding) -> None:
267
279
  resolve_handle(self.current_scope, handle)
268
280
 
281
+ def visit_Expression(self, expr: Expression) -> None:
282
+ if len(self._scope) == 0:
283
+ return
284
+ vrc = VarRefCollector(ignore_duplicated_handles=True, unevaluated=True)
285
+ vrc.visit(ast.parse(expr.expr))
286
+ handles = [
287
+ HandleMetadata(handle=handle)
288
+ for handle in vrc.var_handles
289
+ if handle.name in self.current_scope.variable_states
290
+ and (
291
+ not isinstance(handle, FieldHandleBinding)
292
+ or handle.field not in CLASSICAL_ATTRIBUTES
293
+ )
294
+ ]
295
+ self._handle_inouts(handles)
296
+
297
+ def visit_QuantumExpressionOperation(self, op: QuantumExpressionOperation) -> None:
298
+ self.visit_Expression(op.expression)
299
+ self.visit_QuantumOperation(op)
300
+
269
301
  def _handle_state_changing_ios(
270
302
  self,
271
303
  ios: Sequence[HandleMetadata],
@@ -314,9 +346,6 @@ class StaticSemanticsVisitor(Visitor):
314
346
  )
315
347
 
316
348
  def _handle_inouts(self, inouts: Sequence[HandleMetadata]) -> None:
317
- sliced_handles = set()
318
- whole_handles = set()
319
-
320
349
  for handle_metadata in inouts:
321
350
  handle_binding = handle_metadata.handle
322
351
 
@@ -345,18 +374,6 @@ class StaticSemanticsVisitor(Visitor):
345
374
  f"{location}"
346
375
  )
347
376
 
348
- if isinstance(
349
- handle_binding, (SlicedHandleBinding, SubscriptHandleBinding)
350
- ):
351
- sliced_handles.add(handle_binding.name)
352
- else:
353
- whole_handles.add(handle_binding.name)
354
-
355
- for handle in sliced_handles & whole_handles:
356
- self._error_manager.add_error(
357
- f"Invalid use of inout handle {handle!r}, used both in slice or subscript and whole"
358
- )
359
-
360
377
 
361
378
  def resolve_function_calls(
362
379
  root: Any,
@@ -374,6 +391,7 @@ def resolve_function_calls(
374
391
  def static_semantics_analysis_pass(
375
392
  model: Model, error_type: Optional[type[Exception]] = ClassiqSemanticError
376
393
  ) -> None:
394
+ _check_function_name_collisions(model, error_type)
377
395
  QStructAnnotator().visit(model)
378
396
  StaticSemanticsVisitor(
379
397
  {**BUILTIN_FUNCTION_DECLARATIONS, **model.function_dict},
@@ -10,6 +10,7 @@ from classiq.interface.model.quantum_function_declaration import (
10
10
  QuantumFunctionDeclaration,
11
11
  )
12
12
  from classiq.interface.model.quantum_lambda_function import (
13
+ OperandIdentifier,
13
14
  QuantumLambdaFunction,
14
15
  QuantumOperand,
15
16
  )
@@ -56,16 +57,19 @@ def _check_operand_against_declaration(
56
57
  )
57
58
  return
58
59
  operand_arg_decl: AnonQuantumFunctionDeclaration
59
- if isinstance(operand_argument, str):
60
- if operand_argument not in function_dict:
60
+ operand_argument_for_decl = operand_argument
61
+ if isinstance(operand_argument_for_decl, OperandIdentifier):
62
+ operand_argument_for_decl = operand_argument_for_decl.name
63
+ if isinstance(operand_argument_for_decl, str):
64
+ if operand_argument_for_decl not in function_dict:
61
65
  ErrorManager().add_error(
62
66
  f"{operand_argument!r} argument to {func_name!r} is not a "
63
67
  f"registered function."
64
68
  )
65
69
  return
66
- operand_arg_decl = function_dict[operand_argument]
67
- elif isinstance(operand_argument, QuantumLambdaFunction):
68
- operand_arg_decl = operand_argument.func_decl
70
+ operand_arg_decl = function_dict[operand_argument_for_decl]
71
+ elif isinstance(operand_argument_for_decl, QuantumLambdaFunction):
72
+ operand_arg_decl = operand_argument_for_decl.func_decl
69
73
  else:
70
74
  raise ClassiqError(
71
75
  f"{str(operand_argument)!r} argument to {func_name!r} is not a "
@@ -0,0 +1,23 @@
1
+ from typing import Optional
2
+
3
+ from classiq.interface.model.model import Model
4
+
5
+ from classiq.qmod.builtins.functions import CORE_LIB_DECLS
6
+
7
+
8
+ def _check_function_name_collisions(
9
+ model: Model, error_type: Optional[type[Exception]]
10
+ ) -> None:
11
+ if error_type is None:
12
+ return
13
+ redefined_functions = [
14
+ function.name
15
+ for function in CORE_LIB_DECLS
16
+ if function.name in model.function_dict
17
+ ]
18
+ if len(redefined_functions) == 1:
19
+ raise error_type(
20
+ f"Cannot redefine built-in function {redefined_functions[0]!r}"
21
+ )
22
+ elif len(redefined_functions) > 1:
23
+ raise error_type(f"Cannot redefine built-in functions: {redefined_functions}")
classiq/qmod/symbolic.py CHANGED
@@ -303,70 +303,70 @@ def subscript(
303
303
 
304
304
 
305
305
  __all__ = [
306
- "pi",
306
+ "Catalan",
307
307
  "E",
308
- "I",
309
- "GoldenRatio",
310
308
  "EulerGamma",
311
- "Catalan",
312
- "sin",
313
- "cos",
314
- "tan",
315
- "cot",
316
- "sec",
317
- "csc",
318
- "asin",
309
+ "GoldenRatio",
310
+ "I",
311
+ "Piecewise",
312
+ "abs",
319
313
  "acos",
320
- "atan",
314
+ "acosh",
321
315
  "acot",
322
- "asec",
316
+ "acoth",
323
317
  "acsc",
324
- "sinh",
325
- "cosh",
326
- "tanh",
327
- "coth",
328
- "sech",
329
- "csch",
318
+ "asec",
319
+ "asech",
320
+ "asin",
330
321
  "asinh",
331
- "acosh",
322
+ "atan",
332
323
  "atanh",
333
- "acoth",
334
- "asech",
335
- "exp",
336
- "log",
337
- "ln",
338
- "sqrt",
339
- "abs",
340
- "floor",
324
+ "bell",
325
+ "bernoulli",
326
+ "besseli",
327
+ "besselj",
328
+ "besselk",
329
+ "bessely",
330
+ "beta",
331
+ "binomial",
332
+ "catalan",
341
333
  "ceiling",
334
+ "cos",
335
+ "cosh",
336
+ "cot",
337
+ "coth",
338
+ "csc",
339
+ "csch",
340
+ "dirichlet_eta",
342
341
  "erf",
343
342
  "erfc",
343
+ "euler",
344
+ "exp",
345
+ "factorial",
346
+ "floor",
344
347
  "gamma",
345
- "beta",
346
- "besselj",
347
- "bessely",
348
- "besseli",
349
- "besselk",
350
- "dirichlet_eta",
351
- "polygamma",
348
+ "ln",
349
+ "log",
352
350
  "loggamma",
353
- "factorial",
354
- "binomial",
355
- "subfactorial",
356
- "primorial",
357
- "bell",
358
- "bernoulli",
359
- "euler",
360
- "catalan",
361
- "Piecewise",
362
- "max",
363
- "min",
364
351
  "logical_and",
365
- "logical_or",
366
352
  "logical_not",
353
+ "logical_or",
354
+ "max",
355
+ "min",
367
356
  "mod_inverse",
357
+ "pi",
358
+ "polygamma",
359
+ "primorial",
360
+ "sec",
361
+ "sech",
362
+ "sin",
363
+ "sinh",
364
+ "sqrt",
365
+ "subfactorial",
368
366
  "subscript",
369
367
  "sum",
368
+ "tan",
369
+ "tanh",
370
370
  ]
371
371
 
372
372
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: classiq
3
- Version: 0.60.0
3
+ Version: 0.61.0
4
4
  Summary: Classiq's Python SDK for quantum computing
5
5
  Home-page: https://classiq.io
6
6
  License: Proprietary