classiq 0.89.0__py3-none-any.whl → 0.91.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 (108) hide show
  1. classiq/__init__.py +1 -0
  2. classiq/_internals/api_wrapper.py +16 -32
  3. classiq/analyzer/show_interactive_hack.py +26 -1
  4. classiq/applications/chemistry/chemistry_model_constructor.py +14 -2
  5. classiq/applications/combinatorial_helpers/pyomo_utils.py +9 -6
  6. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
  7. classiq/applications/combinatorial_optimization/combinatorial_problem.py +16 -8
  8. classiq/evaluators/classical_expression.py +63 -41
  9. classiq/evaluators/control.py +31 -52
  10. classiq/evaluators/expression_evaluator.py +31 -127
  11. classiq/evaluators/parameter_types.py +200 -104
  12. classiq/evaluators/qmod_annotated_expression.py +3 -1
  13. classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +10 -3
  14. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +12 -37
  15. classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +8 -17
  16. classiq/evaluators/qmod_node_evaluators/measurement_evaluation.py +1 -1
  17. classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +7 -1
  18. classiq/evaluators/qmod_node_evaluators/name_evaluation.py +0 -1
  19. classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +9 -1
  20. classiq/evaluators/qmod_node_evaluators/utils.py +33 -8
  21. classiq/evaluators/qmod_type_inference/classical_type_inference.py +4 -7
  22. classiq/interface/_version.py +1 -1
  23. classiq/interface/analyzer/analysis_params.py +1 -25
  24. classiq/interface/analyzer/result.py +4 -0
  25. classiq/interface/chemistry/ground_state_problem.py +16 -2
  26. classiq/interface/executor/optimizer_preferences.py +0 -112
  27. classiq/interface/executor/result.py +22 -3
  28. classiq/interface/generator/application_apis/chemistry_declarations.py +3 -1
  29. classiq/interface/generator/arith/arithmetic_expression_validator.py +2 -7
  30. classiq/interface/generator/expressions/evaluated_expression.py +3 -13
  31. classiq/interface/generator/expressions/expression_types.py +10 -22
  32. classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +3 -8
  33. classiq/interface/generator/expressions/proxies/classical/classical_proxy.py +2 -2
  34. classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +1 -2
  35. classiq/interface/generator/functions/classical_type.py +2 -5
  36. classiq/interface/generator/functions/concrete_types.py +1 -1
  37. classiq/interface/generator/functions/type_name.py +0 -12
  38. classiq/interface/generator/generated_circuit_data.py +4 -0
  39. classiq/interface/generator/preferences/qasm_to_qmod_params.py +14 -0
  40. classiq/interface/helpers/model_normalizer.py +0 -6
  41. classiq/interface/ide/visual_model.py +1 -0
  42. classiq/interface/model/handle_binding.py +1 -1
  43. classiq/interface/model/port_declaration.py +2 -1
  44. classiq/interface/model/quantum_expressions/arithmetic_operation.py +16 -12
  45. classiq/interface/model/quantum_type.py +1 -40
  46. classiq/interface/server/routes.py +2 -3
  47. classiq/model_expansions/capturing/captured_vars.py +10 -3
  48. classiq/model_expansions/closure.py +8 -0
  49. classiq/model_expansions/function_builder.py +18 -2
  50. classiq/model_expansions/interpreters/base_interpreter.py +84 -22
  51. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +1 -11
  52. classiq/model_expansions/interpreters/generative_interpreter.py +67 -20
  53. classiq/model_expansions/quantum_operations/allocate.py +92 -21
  54. classiq/model_expansions/quantum_operations/assignment_result_processor.py +28 -27
  55. classiq/model_expansions/quantum_operations/call_emitter.py +32 -26
  56. classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -2
  57. classiq/model_expansions/quantum_operations/emitter.py +50 -70
  58. classiq/model_expansions/quantum_operations/expression_evaluator.py +62 -7
  59. classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -5
  60. classiq/model_expansions/quantum_operations/variable_decleration.py +16 -11
  61. classiq/model_expansions/scope.py +39 -41
  62. classiq/model_expansions/scope_initialization.py +3 -6
  63. classiq/model_expansions/transformers/model_renamer.py +35 -64
  64. classiq/model_expansions/transformers/type_modifier_inference.py +6 -6
  65. classiq/model_expansions/utils/handles_collector.py +7 -0
  66. classiq/model_expansions/visitors/boolean_expression_transformers.py +7 -31
  67. classiq/model_expansions/visitors/symbolic_param_inference.py +9 -3
  68. classiq/open_library/functions/state_preparation.py +3 -3
  69. classiq/qmod/builtins/functions/allocation.py +8 -8
  70. classiq/qmod/builtins/functions/arithmetic.py +1 -1
  71. classiq/qmod/builtins/functions/chemistry.py +64 -0
  72. classiq/qmod/builtins/functions/exponentiation.py +7 -13
  73. classiq/qmod/builtins/functions/qsvm.py +1 -1
  74. classiq/qmod/builtins/operations.py +42 -10
  75. classiq/qmod/generative.py +2 -4
  76. classiq/qmod/native/pretty_printer.py +1 -1
  77. classiq/qmod/pretty_print/pretty_printer.py +1 -1
  78. classiq/qmod/qmod_constant.py +1 -1
  79. classiq/qmod/qmod_parameter.py +2 -2
  80. classiq/qmod/qmod_variable.py +18 -19
  81. classiq/qmod/quantum_expandable.py +1 -1
  82. classiq/qmod/semantics/error_manager.py +34 -15
  83. classiq/qmod/symbolic.py +15 -4
  84. classiq/qmod/utilities.py +4 -1
  85. classiq/synthesis.py +38 -3
  86. classiq/visualization.py +1 -1
  87. {classiq-0.89.0.dist-info → classiq-0.91.0.dist-info}/METADATA +1 -1
  88. {classiq-0.89.0.dist-info → classiq-0.91.0.dist-info}/RECORD +89 -107
  89. classiq/evaluators/arg_type_match.py +0 -168
  90. classiq/evaluators/classical_type_inference.py +0 -121
  91. classiq/interface/combinatorial_optimization/optimization_problem.py +0 -17
  92. classiq/interface/combinatorial_optimization/result.py +0 -9
  93. classiq/interface/generator/expressions/handle_identifier.py +0 -6
  94. classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +0 -41
  95. classiq/interface/generator/expressions/proxies/quantum/__init__.py +0 -0
  96. classiq/interface/generator/expressions/proxies/quantum/qmod_qarray_proxy.py +0 -80
  97. classiq/interface/generator/expressions/proxies/quantum/qmod_qscalar_proxy.py +0 -77
  98. classiq/interface/generator/expressions/proxies/quantum/qmod_qstruct_proxy.py +0 -38
  99. classiq/interface/generator/expressions/proxies/quantum/qmod_sized_proxy.py +0 -39
  100. classiq/interface/generator/expressions/type_proxy.py +0 -10
  101. classiq/model_expansions/atomic_expression_functions_defs.py +0 -413
  102. classiq/model_expansions/model_tables.py +0 -18
  103. classiq/model_expansions/sympy_conversion/__init__.py +0 -0
  104. classiq/model_expansions/sympy_conversion/expression_to_sympy.py +0 -181
  105. classiq/model_expansions/sympy_conversion/sympy_to_python.py +0 -132
  106. classiq/model_expansions/transformers/ast_renamer.py +0 -26
  107. classiq/model_expansions/utils/sympy_utils.py +0 -24
  108. {classiq-0.89.0.dist-info → classiq-0.91.0.dist-info}/WHEEL +0 -0
@@ -1,3 +1,7 @@
1
+ import warnings
2
+
3
+ from classiq.interface.exceptions import ClassiqDeprecationWarning
4
+
1
5
  from classiq.qmod.builtins.structs import (
2
6
  FockHamiltonianProblem,
3
7
  MoleculeProblem,
@@ -13,6 +17,16 @@ def molecule_ucc(
13
17
  excitations: CArray[CInt],
14
18
  qbv: QArray[QBit],
15
19
  ) -> None:
20
+ warnings.warn(
21
+ (
22
+ "The function `molecule_ucc` is deprecated and will no "
23
+ "longer be supported starting on 2025-09-18 at the earliest. "
24
+ "For more information on Classiq's chemistry application, see "
25
+ "https://docs.classiq.io/latest/explore/applications/chemistry/classiq_chemistry_application/classiq_chemistry_application/."
26
+ ),
27
+ category=ClassiqDeprecationWarning,
28
+ stacklevel=2,
29
+ )
16
30
  pass
17
31
 
18
32
 
@@ -22,6 +36,16 @@ def molecule_hva(
22
36
  reps: CInt,
23
37
  qbv: QArray[QBit],
24
38
  ) -> None:
39
+ warnings.warn(
40
+ (
41
+ "The function `molecule_hva` is deprecated and will no "
42
+ "longer be supported starting on 2025-09-18 at the earliest. "
43
+ "For more information on Classiq's chemistry application, see "
44
+ "https://docs.classiq.io/latest/explore/applications/chemistry/classiq_chemistry_application/classiq_chemistry_application/."
45
+ ),
46
+ category=ClassiqDeprecationWarning,
47
+ stacklevel=2,
48
+ )
25
49
  pass
26
50
 
27
51
 
@@ -30,6 +54,16 @@ def molecule_hartree_fock(
30
54
  molecule_problem: MoleculeProblem,
31
55
  qbv: QArray[QBit],
32
56
  ) -> None:
57
+ warnings.warn(
58
+ (
59
+ "The function `molecule_hartree_fock` is deprecated and will no "
60
+ "longer be supported starting on 2025-09-18 at the earliest. "
61
+ "For more information on Classiq's chemistry application, see "
62
+ "https://docs.classiq.io/latest/explore/applications/chemistry/classiq_chemistry_application/classiq_chemistry_application/."
63
+ ),
64
+ category=ClassiqDeprecationWarning,
65
+ stacklevel=2,
66
+ )
33
67
  pass
34
68
 
35
69
 
@@ -39,6 +73,16 @@ def fock_hamiltonian_ucc(
39
73
  excitations: CArray[CInt],
40
74
  qbv: QArray[QBit],
41
75
  ) -> None:
76
+ warnings.warn(
77
+ (
78
+ "The function `fock_hamiltonian_ucc` is deprecated and will no "
79
+ "longer be supported starting on 2025-09-18 at the earliest. "
80
+ "For more information on Classiq's chemistry application, see "
81
+ "https://docs.classiq.io/latest/explore/applications/chemistry/classiq_chemistry_application/classiq_chemistry_application/."
82
+ ),
83
+ category=ClassiqDeprecationWarning,
84
+ stacklevel=2,
85
+ )
42
86
  pass
43
87
 
44
88
 
@@ -48,6 +92,16 @@ def fock_hamiltonian_hva(
48
92
  reps: CInt,
49
93
  qbv: QArray[QBit],
50
94
  ) -> None:
95
+ warnings.warn(
96
+ (
97
+ "The function `fock_hamiltonian_hva` is deprecated and will no "
98
+ "longer be supported starting on 2025-09-18 at the earliest. "
99
+ "For more information on Classiq's chemistry application, see "
100
+ "https://docs.classiq.io/latest/explore/applications/chemistry/classiq_chemistry_application/classiq_chemistry_application/."
101
+ ),
102
+ category=ClassiqDeprecationWarning,
103
+ stacklevel=2,
104
+ )
51
105
  pass
52
106
 
53
107
 
@@ -56,4 +110,14 @@ def fock_hamiltonian_hartree_fock(
56
110
  fock_hamiltonian_problem: FockHamiltonianProblem,
57
111
  qbv: QArray[QBit],
58
112
  ) -> None:
113
+ warnings.warn(
114
+ (
115
+ "The function `fock_hamiltonian_hartree_fock` is deprecated and will no "
116
+ "longer be supported starting on 2025-09-18 at the earliest. "
117
+ "For more information on Classiq's chemistry application, see "
118
+ "https://docs.classiq.io/latest/explore/applications/chemistry/classiq_chemistry_application/classiq_chemistry_application/."
119
+ ),
120
+ category=ClassiqDeprecationWarning,
121
+ stacklevel=2,
122
+ )
59
123
  pass
@@ -14,7 +14,7 @@ from classiq.qmod.qmod_variable import QArray, QBit
14
14
  def single_pauli_exponent(
15
15
  pauli_string: CArray[Pauli],
16
16
  coefficient: CReal,
17
- qbv: QArray[QBit, Literal["get_field(pauli_string, 'len')"]],
17
+ qbv: QArray[QBit, Literal["pauli_string.len"]],
18
18
  ) -> None:
19
19
  """
20
20
  [Qmod core-library function]
@@ -33,9 +33,7 @@ def single_pauli_exponent(
33
33
  def commuting_paulis_exponent(
34
34
  pauli_operator: CArray[PauliTerm],
35
35
  evolution_coefficient: CReal,
36
- qbv: QArray[
37
- QBit, Literal["get_field(get_field(pauli_operator[0], 'pauli'), 'len')"]
38
- ],
36
+ qbv: QArray[QBit, Literal["pauli_operator[0].pauli.len"]],
39
37
  ) -> None:
40
38
  """
41
39
  [Qmod core-library function]
@@ -113,11 +111,11 @@ def multi_suzuki_trotter(
113
111
  @qfunc(external=True)
114
112
  def parametric_suzuki_trotter(
115
113
  paulis: CArray[CArray[Pauli]],
116
- coefficients: CArray[CReal, Literal["get_field(paulis, 'len')"]],
114
+ coefficients: CArray[CReal, Literal["paulis.len"]],
117
115
  evolution_coefficient: CReal,
118
116
  order: CInt,
119
117
  repetitions: CInt,
120
- qbv: QArray[QBit, Literal["get_field(paulis[0], 'len')"]],
118
+ qbv: QArray[QBit, Literal["paulis[0].len"]],
121
119
  ) -> None:
122
120
  """
123
121
  [Qmod core-library function]
@@ -147,7 +145,7 @@ def sparse_suzuki_trotter(
147
145
  evolution_coefficient: CReal,
148
146
  order: CInt,
149
147
  repetitions: CInt,
150
- qbv: QArray[QBit, Literal["get_field(pauli_operator, 'num_qubits')"]],
148
+ qbv: QArray[QBit, Literal["pauli_operator.num_qubits"]],
151
149
  ) -> None:
152
150
  """
153
151
  [Qmod core-library function]
@@ -174,9 +172,7 @@ def qdrift(
174
172
  pauli_operator: CArray[PauliTerm],
175
173
  evolution_coefficient: CReal,
176
174
  num_qdrift: CInt,
177
- qbv: QArray[
178
- QBit, Literal["get_field(get_field(pauli_operator[0], 'pauli'), 'len')"]
179
- ],
175
+ qbv: QArray[QBit, Literal["pauli_operator[0].pauli.len"]],
180
176
  ) -> None:
181
177
  """
182
178
  [Qmod core-library function]
@@ -199,9 +195,7 @@ def exponentiation_with_depth_constraint(
199
195
  pauli_operator: CArray[PauliTerm],
200
196
  evolution_coefficient: CReal,
201
197
  max_depth: CInt,
202
- qbv: QArray[
203
- QBit, Literal["get_field(get_field(pauli_operator[0], 'pauli'), 'len')"]
204
- ],
198
+ qbv: QArray[QBit, Literal["pauli_operator[0].pauli.len"]],
205
199
  ) -> None:
206
200
  """
207
201
  [Qmod core-library function]
@@ -11,7 +11,7 @@ from classiq.qmod.qmod_variable import QArray, QBit
11
11
  @qfunc(external=True)
12
12
  def pauli_feature_map(
13
13
  feature_map: QSVMFeatureMapPauli,
14
- qbv: QArray[QBit, Literal["get_field(feature_map, 'feature_dimension')"]],
14
+ qbv: QArray[QBit, Literal["feature_map.feature_dimension"]],
15
15
  ) -> None:
16
16
  pass
17
17
 
@@ -1,5 +1,6 @@
1
1
  import inspect
2
2
  import sys
3
+ import warnings
3
4
  from collections.abc import Mapping
4
5
  from types import FrameType
5
6
  from typing import (
@@ -12,7 +13,7 @@ from typing import (
12
13
  overload,
13
14
  )
14
15
 
15
- from classiq.interface.exceptions import ClassiqValueError
16
+ from classiq.interface.exceptions import ClassiqDeprecationWarning, ClassiqValueError
16
17
  from classiq.interface.generator.expressions.expression import Expression
17
18
  from classiq.interface.generator.functions.builtins.internal_operators import (
18
19
  REPEAT_OPERATOR_NAME,
@@ -516,27 +517,58 @@ def invert(stmt_block: Union[QCallable, Callable[[], Statements]]) -> None:
516
517
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(invert_stmt)
517
518
 
518
519
 
520
+ @overload
521
+ def phase(
522
+ phase_expr: Union[SymbolicExpr, float], theta: Union[SymbolicExpr, float] = 1.0
523
+ ) -> None:
524
+ pass
525
+
526
+
527
+ @overload
528
+ def phase(
529
+ *, expr: Union[SymbolicExpr, float], theta: Union[SymbolicExpr, float] = 1.0
530
+ ) -> None:
531
+ pass
532
+
533
+
519
534
  @suppress_return_value
520
- def phase(expr: SymbolicExpr, theta: float = 1.0) -> None:
535
+ def phase(
536
+ phase_expr: Union[SymbolicExpr, float, None] = None,
537
+ theta: Union[SymbolicExpr, float] = 1.0,
538
+ expr: Any = None,
539
+ ) -> None:
521
540
  """
522
- Applies a state-dependent phase shift to the quantum state.
541
+ Applies a state-dependent or fixed phase shift (Z rotation) to the quantum state.
523
542
 
524
- This operation multiplies each basis state |x> by a complex phase factor `theta * expr(x)`,
525
- where `expr` is a symbolic expression dependent on the state value `x`, and `theta` is a scalar multiplier.
543
+ This operation multiplies each computational-basis state $|x_1,x_2,\\ldots,x_n\\rangle$
544
+ by a complex phase factor $\\theta * \\text{phase_expr}(x_1,x_2,\\ldots,x_n)$, where
545
+ `phase_expr` is a symbolic expression that contains quantum variables $x_1,x_2,\\ldots,x_n$,
546
+ and `theta` is a scalar multiplier. If `phase_expr` contains no quantum variables,
547
+ all states are rotated by the same fixed angle.
526
548
 
527
549
  Args:
528
- expr: A symbolic expression that evaluates to an angle (in radians) as a function of the quantum state value `x`.
529
- theta: (Optional) A scalar multiplier for the evaluated expression. Defaults to 1.0.
550
+ phase_expr: A symbolic expression that evaluates to an angle (in radians) as a function of the state of the quantum variables occurring in it, if any, or otherwise a fixed value. Execution parameters are only allowed if no quantum variables occur in the expression.
551
+ theta: (Optional, allowed only together with quantum expressions) A scalar multiplier for the evaluated expression, optionally containing execution parameters. Defaults to 1.0.
530
552
 
531
553
  Note:
532
- The `phase` operation is equivalent to a Z-rotation up to a global phase. It is commonly used
533
- to apply relative phase shifts conditioned on the quantum state.
554
+ The `phase` statement is a generalization of the `PHASE()` atomic function, and
555
+ they are equivalent when the phase_expr is a single-qubit variable.
534
556
  """
535
557
  assert QCallable.CURRENT_EXPANDABLE is not None
558
+ if expr is not None:
559
+ warnings.warn(
560
+ "Parameter 'expr' of function 'phase' has been renamed to "
561
+ "'phase_expr'. Parameter 'expr' will no longer be supported starting on "
562
+ "2025-09-19 at the earliest.\nHint: Change `phase(expr=..., theta=...)` to "
563
+ "`phase(phase_expr=..., theta=...)` or `phase(..., ...)`.",
564
+ category=ClassiqDeprecationWarning,
565
+ stacklevel=2,
566
+ )
567
+ phase_expr = expr
536
568
  source_ref = get_source_ref(sys._getframe(1))
537
569
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
538
570
  PhaseOperation(
539
- expression=Expression(expr=str(expr)),
571
+ expression=Expression(expr=str(phase_expr)),
540
572
  theta=Expression(expr=str(theta)),
541
573
  source_ref=source_ref,
542
574
  )
@@ -4,10 +4,8 @@ from typing import TYPE_CHECKING, Any, Optional
4
4
 
5
5
  from classiq.interface.exceptions import ClassiqError
6
6
  from classiq.interface.generator.expressions.expression import Expression
7
- from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
8
- AnyClassicalValue,
9
- )
10
7
 
8
+ from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
11
9
  from classiq.qmod.cparam import CParamScalar
12
10
 
13
11
  if TYPE_CHECKING:
@@ -47,6 +45,6 @@ def get_frontend_interpreter() -> "GenerativeInterpreter":
47
45
 
48
46
  def interpret_expression(expr: str) -> Any:
49
47
  val = get_frontend_interpreter().evaluate(Expression(expr=expr)).value
50
- if isinstance(val, AnyClassicalValue):
48
+ if isinstance(val, QmodAnnotatedExpression):
51
49
  return CParamScalar(str(val))
52
50
  return val
@@ -312,7 +312,7 @@ class DSLPrettyPrinter(ModelVisitor):
312
312
  return control
313
313
 
314
314
  def visit_PhaseOperation(self, op: PhaseOperation) -> str:
315
- theta = f", {self.visit(op.theta)}" if op.theta else ""
315
+ theta = f", {self.visit(op.theta)}" if op.theta.expr != "1.0" else ""
316
316
  phase = f"{self._indent}phase ({self.visit(op.expression)}{theta});\n"
317
317
  return phase
318
318
 
@@ -461,7 +461,7 @@ class PythonPrettyPrinter(ModelVisitor):
461
461
 
462
462
  def visit_PhaseOperation(self, op: PhaseOperation) -> str:
463
463
  self._imports["phase"] = 1
464
- theta = f", {self.visit(op.theta)}" if op.theta is not None else ""
464
+ theta = f", {self.visit(op.theta)}" if op.theta.expr != "1.0" else ""
465
465
  return f"{self._indent}phase({self.visit(op.expression)}{theta})\n"
466
466
 
467
467
  def visit_ClassicalIf(self, op: ClassicalIf) -> str:
@@ -138,7 +138,7 @@ class QConstant(SymbolicExpr):
138
138
  f"Constant {self.name!r} of type {self._py_type.__name__!r} does not "
139
139
  f"have a 'len' property"
140
140
  )
141
- len_expr = f"get_field({self.name}, 'len')"
141
+ len_expr = f"{self.name}.len"
142
142
  if is_generative_mode():
143
143
  return interpret_expression(len_expr)
144
144
  return cast(int, CParamScalar(len_expr))
@@ -100,7 +100,7 @@ class CParamList(CParam):
100
100
  if is_generative_mode():
101
101
  with generative_mode_context(False):
102
102
  return interpret_expression(str(self.len))
103
- return CParamScalar(f"get_field({self}, 'len')")
103
+ return CParamScalar(f"{self}.len")
104
104
 
105
105
 
106
106
  class CParamStruct(CParam):
@@ -135,7 +135,7 @@ class CParamStruct(CParam):
135
135
  )
136
136
 
137
137
  return create_param(
138
- f"get_field({variable_name},{field_name!r})",
138
+ f"{variable_name}.{field_name}",
139
139
  field_type.model_copy(deep=True),
140
140
  qmodule=qmodule,
141
141
  )
@@ -31,10 +31,6 @@ from classiq.interface.exceptions import (
31
31
  from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
32
32
  from classiq.interface.generator.expressions.expression import Expression
33
33
  from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
34
- from classiq.interface.generator.expressions.proxies.quantum.qmod_qarray_proxy import (
35
- ILLEGAL_SLICE_MSG,
36
- ILLEGAL_SLICING_STEP_MSG,
37
- )
38
34
  from classiq.interface.generator.functions.concrete_types import ConcreteQuantumType
39
35
  from classiq.interface.generator.functions.port_declaration import (
40
36
  PortDeclarationDirection,
@@ -83,6 +79,9 @@ from classiq.qmod.utilities import (
83
79
  version_portable_get_args,
84
80
  )
85
81
 
82
+ ILLEGAL_SLICING_STEP_MSG = "Slicing with a step of a quantum variable is not supported"
83
+ ILLEGAL_SLICE_MSG = "Quantum array slice must be of the form [<int-value>:<int-value>]."
84
+
86
85
 
87
86
  @contextmanager
88
87
  def _no_current_expandable() -> Iterator[None]:
@@ -156,7 +155,7 @@ class QVar(Symbolic):
156
155
  if is_generative_mode():
157
156
  with generative_mode_context(False):
158
157
  return interpret_expression(str(self.size))
159
- return CParamScalar(f"get_field({self}, 'size')")
158
+ return CParamScalar(f"{self}.size")
160
159
 
161
160
  @property
162
161
  def type_name(self) -> str:
@@ -229,8 +228,8 @@ class QScalar(QVar, SymbolicExpr):
229
228
 
230
229
  def __ior__(self, other: Any) -> Self:
231
230
  if not isinstance(other, SYMBOLIC_TYPES):
232
- raise TypeError(
233
- f"Invalid argument {other!r} for out-of-place arithmetic operation"
231
+ raise ClassiqValueError(
232
+ f"Invalid argument {str(other)!r} for out-of-place arithmetic operation"
234
233
  )
235
234
 
236
235
  self._insert_arith_operation(
@@ -240,8 +239,8 @@ class QScalar(QVar, SymbolicExpr):
240
239
 
241
240
  def __ixor__(self, other: Any) -> Self:
242
241
  if not isinstance(other, SYMBOLIC_TYPES):
243
- raise TypeError(
244
- f"Invalid argument {other!r} for in-place arithmetic operation"
242
+ raise ClassiqValueError(
243
+ f"Invalid argument {str(other)!r} for in-place arithmetic operation"
245
244
  )
246
245
 
247
246
  self._insert_arith_operation(
@@ -251,8 +250,8 @@ class QScalar(QVar, SymbolicExpr):
251
250
 
252
251
  def __iadd__(self, other: Any) -> Self:
253
252
  if not isinstance(other, SYMBOLIC_TYPES):
254
- raise TypeError(
255
- f"Invalid argument {other!r} for in-place arithmetic operation"
253
+ raise ClassiqValueError(
254
+ f"Invalid argument {str(other)!r} for in-place arithmetic operation"
256
255
  )
257
256
 
258
257
  self._insert_arith_operation(
@@ -262,8 +261,8 @@ class QScalar(QVar, SymbolicExpr):
262
261
 
263
262
  def __imul__(self, other: Any) -> Self:
264
263
  if not isinstance(other, SYMBOLIC_TYPES):
265
- raise TypeError(
266
- f"Invalid argument {other!r} for out of ampltiude encoding operation"
264
+ raise ClassiqValueError(
265
+ f"Invalid argument {str(other)!r} for out of ampltiude encoding operation"
267
266
  )
268
267
 
269
268
  self._insert_amplitude_loading(other, get_source_ref(sys._getframe(1)))
@@ -432,7 +431,7 @@ class QNum(Generic[_P], QScalar):
432
431
  name: Union[None, str, HandleBinding] = None,
433
432
  size: Union[int, CInt, Expression, SymbolicExpr, None] = None,
434
433
  is_signed: Union[bool, CBool, Expression, SymbolicExpr, None] = None,
435
- fraction_digits: Union[int, CInt, Expression, None] = None,
434
+ fraction_digits: Union[int, CInt, Expression, SymbolicExpr, None] = None,
436
435
  _expr_str: Optional[str] = None,
437
436
  ):
438
437
  if size is None and (is_signed is not None or fraction_digits is not None):
@@ -485,14 +484,14 @@ class QNum(Generic[_P], QScalar):
485
484
  if is_generative_mode():
486
485
  with generative_mode_context(False):
487
486
  return interpret_expression(str(self.fraction_digits))
488
- return CParamScalar(f"get_field({self}, 'fraction_digits')")
487
+ return CParamScalar(f"{self}.fraction_digits")
489
488
 
490
489
  @property
491
490
  def is_signed(self) -> Union[CParamScalar, bool]:
492
491
  if is_generative_mode():
493
492
  with generative_mode_context(False):
494
493
  return interpret_expression(str(self.is_signed))
495
- return CParamScalar(f"get_field({self}, 'is_signed')")
494
+ return CParamScalar(f"{self}.is_signed")
496
495
 
497
496
  def get_maximal_bounds(self) -> tuple[float, float]:
498
497
  if not is_generative_mode():
@@ -594,7 +593,7 @@ class QArray(ArrayBase[_P], QVar, NonSymbolicExpr):
594
593
  if is_generative_mode():
595
594
  with generative_mode_context(False):
596
595
  return interpret_expression(str(self.len))
597
- return CParamScalar(f"get_field({self}, 'len')")
596
+ return CParamScalar(f"{self}.len")
598
597
 
599
598
  @classmethod
600
599
  def to_qvar(
@@ -669,7 +668,7 @@ class QStruct(QVar):
669
668
  field_name: field_class.to_qvar(
670
669
  FieldHandleBinding(base_handle=base_handle, field=field_name),
671
670
  field_type,
672
- f"get_field({expr_str if expr_str is not None else str(origin)}, '{field_name}')",
671
+ f"{expr_str if expr_str is not None else str(origin)}.{field_name}",
673
672
  )
674
673
  for field_name, (field_class, field_type) in field_types.items()
675
674
  }
@@ -723,7 +722,7 @@ def _create_qvar_for_qtype(
723
722
  field_name: _create_qvar_for_qtype(
724
723
  field_type,
725
724
  FieldHandleBinding(base_handle=origin, field=field_name),
726
- f"get_field({expr_str if expr_str is not None else str(origin)}, '{field_name}')",
725
+ f"{expr_str if expr_str is not None else str(origin)}.{field_name}",
727
726
  )
728
727
  for field_name, field_type in struct_decl.fields.items()
729
728
  },
@@ -286,7 +286,7 @@ class QTerminalCallable(QCallable):
286
286
  def len(self) -> CParamScalar:
287
287
  if not self.is_list:
288
288
  raise ClassiqValueError("Cannot get length of a non-list operand")
289
- return CParamScalar(f"get_field({self.func_decl.name}, 'len')")
289
+ return CParamScalar(f"{self.func_decl.name}.len")
290
290
 
291
291
  @property
292
292
  def func_decl(self) -> QuantumFunctionDeclaration:
@@ -18,6 +18,7 @@ class ErrorManager:
18
18
  return
19
19
  self._instantiated = True
20
20
  self._errors: list[SourceReferencedError] = []
21
+ self._warnings: list[SourceReferencedError] = []
21
22
  self._current_nodes_stack: list[ASTNode] = []
22
23
  self._call_stack: list[str] = []
23
24
  self._ignore_errors: bool = False
@@ -41,38 +42,56 @@ class ErrorManager:
41
42
  def annotated_errors(self) -> list[str]:
42
43
  return [str(error) for error in self._errors]
43
44
 
45
+ @property
46
+ def annotated_warnings(self) -> list[str]:
47
+ return [str(error) for error in self._warnings]
48
+
44
49
  def add_error(
45
50
  self,
46
51
  error: str,
47
52
  *,
48
53
  source_ref: Optional[SourceReference] = None,
49
54
  function: Optional[str] = None,
55
+ warning: bool = False,
50
56
  ) -> None:
51
- if not self._ignore_errors:
52
- self._errors.append(
53
- SourceReferencedError(
54
- error=error.replace(CLASSIQ_SLACK_COMMUNITY_LINK, ""),
55
- source_ref=(
56
- source_ref
57
- if source_ref is not None
58
- else self._current_source_ref
59
- ),
60
- function=(
61
- function if function is not None else self.current_function
62
- ),
63
- )
64
- )
57
+ if self._ignore_errors:
58
+ return
59
+
60
+ source_ref_error = SourceReferencedError(
61
+ error=error.replace(CLASSIQ_SLACK_COMMUNITY_LINK, ""),
62
+ source_ref=(
63
+ source_ref if source_ref is not None else self._current_source_ref
64
+ ),
65
+ function=(function if function is not None else self.current_function),
66
+ )
67
+ if warning:
68
+ self._warnings.append(source_ref_error)
69
+ else:
70
+ self._errors.append(source_ref_error)
65
71
 
66
72
  def get_errors(self) -> list[SourceReferencedError]:
67
73
  return self._errors
68
74
 
75
+ def get_warnings(self) -> list[SourceReferencedError]:
76
+ return self._warnings
77
+
69
78
  def clear(self) -> None:
79
+ self.clear_errors()
80
+ self.clear_warnings()
81
+
82
+ def clear_errors(self) -> None:
70
83
  self._current_nodes_stack = []
71
84
  self._errors = []
72
85
 
86
+ def clear_warnings(self) -> None:
87
+ self._warnings = []
88
+
73
89
  def has_errors(self) -> bool:
74
90
  return len(self._errors) > 0
75
91
 
92
+ def has_warnings(self) -> bool:
93
+ return len(self._warnings) > 0
94
+
76
95
  def report_errors(
77
96
  self, error_type: type[Exception], mask: Optional[list[int]] = None
78
97
  ) -> None:
@@ -82,7 +101,7 @@ class ErrorManager:
82
101
  if mask is None
83
102
  else [self.annotated_errors[idx] for idx in mask]
84
103
  )
85
- self.clear()
104
+ self.clear_errors()
86
105
  raise error_type("\n\t" + "\n\t".join(errors))
87
106
 
88
107
  @property
classiq/qmod/symbolic.py CHANGED
@@ -11,9 +11,6 @@ from typing import (
11
11
  import numpy as np
12
12
 
13
13
  from classiq.interface.exceptions import ClassiqValueError
14
- from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
15
- subscript_to_str,
16
- )
17
14
 
18
15
  from classiq.qmod import model_state_container
19
16
  from classiq.qmod.declaration_inferrer import python_type_to_qmod
@@ -309,12 +306,26 @@ def sum(arr: SymbolicTypes) -> CParamScalar:
309
306
  return symbolic_function(arr)
310
307
 
311
308
 
309
+ def _subscript_to_str(index: Any) -> str:
310
+ if not isinstance(index, slice):
311
+ return str(index)
312
+ expr = ""
313
+ if index.start is not None:
314
+ expr += str(index.start)
315
+ expr += ":"
316
+ if index.stop is not None:
317
+ expr += str(index.stop)
318
+ if index.step is not None:
319
+ expr += f":{index.step}"
320
+ return expr
321
+
322
+
312
323
  def subscript(
313
324
  array: Union[list, CArray[CReal], np.ndarray],
314
325
  index: Any,
315
326
  ) -> CParamScalar:
316
327
  return CParamScalar(
317
- expr=f"{qmod_val_to_expr_str(_unwrap_numpy(array))}[{subscript_to_str(index)}]"
328
+ expr=f"{qmod_val_to_expr_str(_unwrap_numpy(array))}[{_subscript_to_str(index)}]"
318
329
  )
319
330
 
320
331
 
classiq/qmod/utilities.py CHANGED
@@ -29,6 +29,7 @@ from classiq.interface.generator.expressions.proxies.classical.qmod_struct_insta
29
29
  from classiq.interface.source_reference import SourceReference
30
30
 
31
31
  if TYPE_CHECKING:
32
+ from classiq.qmod.cparam import CParam
32
33
  from classiq.qmod.qmod_variable import QVar
33
34
 
34
35
 
@@ -162,7 +163,9 @@ def suppress_return_value(func: Callable[Params, None]) -> Callable[Params, None
162
163
  return func
163
164
 
164
165
 
165
- Statements = Union[None, list[Union[None, "QVar"]], tuple[Union[None, "QVar"], ...]]
166
+ Statements = Union[
167
+ None, list[Union[None, "QVar", "CParam"]], tuple[Union[None, "QVar", "CParam"], ...]
168
+ ]
166
169
 
167
170
 
168
171
  def _eval_qnum(val: int, size: int, is_signed: bool, fraction_digits: int) -> float: