classiq 0.68.0__py3-none-any.whl → 0.69.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 (47) hide show
  1. classiq/_internals/api_wrapper.py +4 -8
  2. classiq/applications/combinatorial_optimization/combinatorial_problem.py +8 -11
  3. classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
  4. classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
  5. classiq/applications/qnn/torch_utils.py +1 -1
  6. classiq/execution/jobs.py +2 -5
  7. classiq/interface/_version.py +1 -1
  8. classiq/interface/backend/quantum_backend_providers.py +2 -3
  9. classiq/interface/chemistry/operator.py +11 -7
  10. classiq/interface/debug_info/back_ref_util.py +22 -0
  11. classiq/interface/debug_info/debug_info.py +11 -21
  12. classiq/interface/executor/optimizer_preferences.py +1 -0
  13. classiq/interface/generator/arith/arithmetic_param_getters.py +3 -3
  14. classiq/interface/generator/functions/classical_type.py +12 -1
  15. classiq/interface/generator/generated_circuit_data.py +63 -24
  16. classiq/interface/generator/types/builtin_enum_declarations.py +1 -0
  17. classiq/interface/generator/types/enum_declaration.py +12 -1
  18. classiq/interface/ide/visual_model.py +0 -2
  19. classiq/interface/model/quantum_statement.py +1 -1
  20. classiq/interface/server/routes.py +0 -6
  21. classiq/model_expansions/generative_functions.py +4 -3
  22. classiq/model_expansions/quantum_operations/call_emitter.py +0 -13
  23. classiq/model_expansions/scope_initialization.py +5 -19
  24. classiq/open_library/functions/amplitude_amplification.py +3 -7
  25. classiq/open_library/functions/discrete_sine_cosine_transform.py +4 -4
  26. classiq/open_library/functions/grover.py +2 -2
  27. classiq/open_library/functions/hea.py +3 -3
  28. classiq/open_library/functions/modular_exponentiation.py +10 -20
  29. classiq/open_library/functions/qft_functions.py +2 -2
  30. classiq/open_library/functions/qsvt.py +8 -8
  31. classiq/open_library/functions/utility_functions.py +2 -2
  32. classiq/qmod/builtins/classical_functions.py +24 -7
  33. classiq/qmod/builtins/enums.py +1 -0
  34. classiq/qmod/builtins/functions/__init__.py +2 -0
  35. classiq/qmod/builtins/functions/exponentiation.py +24 -0
  36. classiq/qmod/builtins/operations.py +26 -11
  37. classiq/qmod/cparam.py +32 -5
  38. classiq/qmod/python_classical_type.py +10 -4
  39. classiq/qmod/quantum_callable.py +2 -1
  40. classiq/qmod/quantum_function.py +3 -2
  41. classiq/qmod/semantics/error_manager.py +1 -1
  42. classiq/qmod/utilities.py +29 -1
  43. classiq/synthesis.py +9 -6
  44. {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/METADATA +1 -1
  45. {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/RECORD +46 -46
  46. classiq/interface/execution/jobs.py +0 -31
  47. {classiq-0.68.0.dist-info → classiq-0.69.0.dist-info}/WHEEL +0 -0
@@ -3,10 +3,6 @@ from typing import Any
3
3
 
4
4
  from classiq.interface.exceptions import ClassiqError
5
5
  from classiq.interface.generator.constant import Constant
6
- from classiq.interface.generator.expressions.expression_constants import (
7
- CPARAM_EXECUTION_SUFFIX,
8
- RESERVED_EXPRESSIONS,
9
- )
10
6
  from classiq.interface.generator.functions.concrete_types import ConcreteClassicalType
11
7
  from classiq.interface.model.handle_binding import HandleBinding
12
8
  from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model
@@ -129,12 +125,6 @@ def init_builtin_types() -> None:
129
125
  QMODULE.type_decls |= BUILTIN_STRUCT_DECLARATIONS
130
126
 
131
127
 
132
- def _rename_exec_param(param_name: str) -> str:
133
- if param_name in RESERVED_EXPRESSIONS:
134
- return param_name
135
- return param_name + CPARAM_EXECUTION_SUFFIX
136
-
137
-
138
128
  def _add_exec_param_parts_to_scope(param_val: Any, scope: Scope) -> None:
139
129
  if not isinstance(param_val, list):
140
130
  scope[str(param_val)] = Evaluated(value=param_val)
@@ -145,21 +135,17 @@ def _add_exec_param_parts_to_scope(param_val: Any, scope: Scope) -> None:
145
135
 
146
136
  def init_exec_params(model: Model, scope: Scope) -> dict[str, ConcreteClassicalType]:
147
137
  if model.execution_parameters is not None:
148
- exec_params = {
149
- param_name: (param_name, param_type)
150
- for param_name, param_type in model.execution_parameters.items()
151
- }
138
+ exec_params = model.execution_parameters
152
139
  else:
153
140
  exec_params = {
154
- param.name: (_rename_exec_param(param.name), param.classical_type)
141
+ param.name: param.classical_type
155
142
  for param in model.function_dict.get(
156
143
  "_dec_main", model.main_func
157
144
  ).param_decls
158
145
  }
159
- for param_name, (param_rename, param_type) in exec_params.items():
160
- param_val = param_type.as_symbolic(param_rename)
146
+ for param_name, param_type in exec_params.items():
147
+ param_val = param_type.as_symbolic(param_name)
161
148
  scope[param_name] = Evaluated(value=param_val)
162
- scope[param_rename] = Evaluated(value=param_val)
163
149
  if isinstance(param_val, list):
164
150
  _add_exec_param_parts_to_scope(param_val, scope)
165
- return dict(exec_params.values())
151
+ return exec_params
@@ -73,11 +73,9 @@ def exact_amplitude_amplification(
73
73
 
74
74
  extended_qvars: QArray = QArray()
75
75
  within_apply(
76
- lambda: [ # type:ignore[arg-type]
76
+ lambda: [
77
77
  allocate(aux),
78
- bind(
79
- [aux, packed_qvars], extended_qvars
80
- ), # type:ignore[func-returns-value]
78
+ bind([aux, packed_qvars], extended_qvars),
81
79
  ],
82
80
  lambda: amplitude_amplification(
83
81
  k,
@@ -85,9 +83,7 @@ def exact_amplitude_amplification(
85
83
  qvars_[0] == 0, lambda: oracle(qvars_[1 : qvars_.size])
86
84
  ),
87
85
  lambda qvars_: [
88
- space_transform( # type:ignore[func-returns-value]
89
- qvars_[1 : qvars_.size]
90
- ),
86
+ space_transform(qvars_[1 : qvars_.size]),
91
87
  RY(rot_phase, qvars_[0]),
92
88
  ],
93
89
  extended_qvars,
@@ -30,9 +30,9 @@ def _qct_d_operator(x: QNum, q: QBit) -> None:
30
30
  def _qct_pi_operator(x: QArray[QBit], q: QBit) -> None:
31
31
  control(
32
32
  q == 1,
33
- lambda: [ # type:ignore[arg-type]
33
+ lambda: [
34
34
  apply_to_all(X, x),
35
- inplace_add(1, x), # type:ignore[arg-type, func-returns-value]
35
+ inplace_add(1, x), # type:ignore[arg-type]
36
36
  ],
37
37
  )
38
38
 
@@ -70,7 +70,7 @@ def _pi2_operator(x: QArray[QBit], q: QBit) -> None:
70
70
 
71
71
 
72
72
  def _j_operator(q: QBit) -> None:
73
- within_apply(lambda: Z(q), lambda: (S(q), H(q), S(q))) # type:ignore[arg-type]
73
+ within_apply(lambda: Z(q), lambda: (S(q), H(q), S(q)))
74
74
 
75
75
 
76
76
  def _b_t_operator(q: QBit) -> None:
@@ -179,6 +179,6 @@ def qst_type2(x: QArray[QBit]) -> None:
179
179
  """
180
180
  q = QBit()
181
181
  within_apply(
182
- lambda: (allocate(q), X(q)), # type:ignore[arg-type]
182
+ lambda: (allocate(q), X(q)),
183
183
  lambda: qct_qst_type2(x, q),
184
184
  )
@@ -42,7 +42,7 @@ def phase_oracle(
42
42
  """
43
43
  aux = QBit()
44
44
  within_apply(
45
- within=lambda: (allocate(aux), X(aux), H(aux)), # type:ignore[arg-type]
45
+ within=lambda: (allocate(aux), X(aux), H(aux)),
46
46
  apply=lambda: predicate(target, aux),
47
47
  )
48
48
 
@@ -68,7 +68,7 @@ def reflect_about_zero(packed_vars: QArray[QBit]) -> None:
68
68
  lsb = QBit()
69
69
  bind(packed_vars, [msbs, lsb])
70
70
  within_apply(
71
- lambda: (X(lsb), H(lsb)), # type:ignore[arg-type]
71
+ lambda: (X(lsb), H(lsb)),
72
72
  lambda: control(msbs == 0, lambda: X(lsb)),
73
73
  )
74
74
  bind([msbs, lsb], packed_vars)
@@ -58,8 +58,8 @@ def full_hea(
58
58
  """
59
59
  repeat(
60
60
  reps,
61
- lambda r: [ # type:ignore[arg-type]
62
- repeat( # type:ignore[func-returns-value]
61
+ lambda r: [
62
+ repeat(
63
63
  operands_1qubit.len,
64
64
  lambda i1: repeat(
65
65
  num_qubits,
@@ -77,7 +77,7 @@ def full_hea(
77
77
  ),
78
78
  ),
79
79
  ),
80
- repeat( # type:ignore[func-returns-value]
80
+ repeat(
81
81
  operands_2qubit.len,
82
82
  lambda i2: repeat(
83
83
  connectivity_map.len,
@@ -70,23 +70,17 @@ def cc_modular_add(n: CInt, a: CInt, phi_b: QArray[QBit], c1: QBit, c2: QBit) ->
70
70
  aux = QBit()
71
71
 
72
72
  within_apply(
73
- lambda: ( # type:ignore[arg-type]
73
+ lambda: (
74
74
  allocate(aux),
75
- bind([c1, c2], ctrl), # type:ignore[func-returns-value]
75
+ bind([c1, c2], ctrl),
76
76
  ),
77
- lambda: ( # type:ignore[arg-type]
78
- control( # type:ignore[func-returns-value]
79
- ctrl, lambda: qft_space_add_const(a, phi_b)
80
- ),
81
- invert( # type:ignore[func-returns-value]
82
- lambda: qft_space_add_const(n, phi_b)
83
- ),
77
+ lambda: (
78
+ control(ctrl, lambda: qft_space_add_const(a, phi_b)),
79
+ invert(lambda: qft_space_add_const(n, phi_b)),
84
80
  _check_msb(1, phi_b, aux),
85
- control( # type:ignore[func-returns-value]
86
- aux, lambda: qft_space_add_const(n, phi_b)
87
- ),
81
+ control(aux, lambda: qft_space_add_const(n, phi_b)),
88
82
  within_apply(
89
- lambda: invert( # type:ignore[func-returns-value]
83
+ lambda: invert(
90
84
  lambda: control(ctrl, lambda: qft_space_add_const(a, phi_b))
91
85
  ),
92
86
  lambda: _check_msb(0, phi_b, aux),
@@ -160,14 +154,10 @@ def inplace_c_modular_multiply(n: CInt, a: CInt, x: QArray[QBit], ctrl: QBit) ->
160
154
 
161
155
  within_apply(
162
156
  lambda: allocate(x.len + 1, b),
163
- lambda: ( # type:ignore[arg-type]
157
+ lambda: (
164
158
  c_modular_multiply(n, a, b, x, ctrl),
165
- control( # type:ignore[func-returns-value]
166
- ctrl, lambda: multiswap(x, b)
167
- ),
168
- invert( # type:ignore[func-returns-value]
169
- lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl)
170
- ),
159
+ control(ctrl, lambda: multiswap(x, b)),
160
+ invert(lambda: c_modular_multiply(n, mod_inverse(a, n), b, x, ctrl)),
171
161
  ),
172
162
  )
173
163
 
@@ -18,9 +18,9 @@ def qft_no_swap(qbv: QArray[QBit]) -> None:
18
18
  """
19
19
  repeat(
20
20
  qbv.len,
21
- lambda i: ( # type:ignore[arg-type]
21
+ lambda i: (
22
22
  H(qbv[i]),
23
- repeat( # type:ignore[func-returns-value]
23
+ repeat(
24
24
  qbv.len - i - 1,
25
25
  lambda j: CPHASE(
26
26
  theta=pi / (2 ** (j + 1)),
@@ -97,8 +97,8 @@ def qsvt(
97
97
  if_(
98
98
  condition=phase_seq.len % 2 == 1,
99
99
  then=lambda: IDENTITY(qvar),
100
- else_=lambda: ( # type:ignore[arg-type]
101
- u(qvar), # type:ignore[func-returns-value]
100
+ else_=lambda: (
101
+ u(qvar),
102
102
  projector_controlled_phase(
103
103
  phase_seq[phase_seq.len - 1],
104
104
  proj_cnot_2,
@@ -297,8 +297,8 @@ def qsvt_lcu(
297
297
  condition=phase_seq_odd.len > phase_seq_even.len,
298
298
  then=lambda: control(
299
299
  lcu == 0,
300
- lambda: [ # type:ignore[arg-type]
301
- u(qvar), # type:ignore[func-returns-value]
300
+ lambda: [
301
+ u(qvar),
302
302
  projector_controlled_phase(
303
303
  phase_seq_odd[phase_seq_odd.len - 1], proj_cnot_2, qvar, aux
304
304
  ),
@@ -307,8 +307,8 @@ def qsvt_lcu(
307
307
  )
308
308
  if_(
309
309
  condition=phase_seq_odd.len < phase_seq_even.len,
310
- then=lambda: ( # type:ignore[arg-type]
311
- u(qvar), # type:ignore[func-returns-value]
310
+ then=lambda: (
311
+ u(qvar),
312
312
  projector_controlled_double_phase(
313
313
  phase_seq_even[phase_seq_even.len - 1],
314
314
  phase_seq_odd[phase_seq_odd.len - 1],
@@ -319,8 +319,8 @@ def qsvt_lcu(
319
319
  ),
320
320
  control(
321
321
  lcu,
322
- lambda: [ # type:ignore[arg-type]
323
- invert(lambda: u(qvar)), # type:ignore[func-returns-value]
322
+ lambda: [
323
+ invert(lambda: u(qvar)),
324
324
  projector_controlled_phase(
325
325
  phase_seq_even[phase_seq_even.len - 1], proj_cnot_1, qvar, aux
326
326
  ),
@@ -79,8 +79,8 @@ def modular_increment(a: CInt, x: QNum) -> None:
79
79
  )
80
80
  array_cast: QArray = QArray()
81
81
  within_apply(
82
- lambda: ( # type:ignore[arg-type]
83
- bind(x, array_cast), # type:ignore[func-returns-value]
82
+ lambda: (
83
+ bind(x, array_cast),
84
84
  qft(array_cast),
85
85
  ),
86
86
  lambda: repeat(
@@ -12,19 +12,25 @@ def qft_const_adder_phase(
12
12
  value: CInt,
13
13
  reg_len: CInt,
14
14
  ) -> CReal:
15
- return symbolic_function(bit_index, value, reg_len, return_type=CReal)
15
+ return symbolic_function(
16
+ bit_index, value, reg_len, return_type=CReal # type:ignore[type-abstract]
17
+ )
16
18
 
17
19
 
18
20
  def fock_hamiltonian_problem_to_hamiltonian(
19
21
  problem: FockHamiltonianProblem,
20
22
  ) -> CArray[PauliTerm]:
21
- return symbolic_function(problem, return_type=CArray[PauliTerm])
23
+ return symbolic_function(
24
+ problem, return_type=CArray[PauliTerm] # type:ignore[type-abstract]
25
+ )
22
26
 
23
27
 
24
28
  def molecule_problem_to_hamiltonian(
25
29
  problem: MoleculeProblem,
26
30
  ) -> CArray[PauliTerm]:
27
- return symbolic_function(problem, return_type=CArray[PauliTerm])
31
+ return symbolic_function(
32
+ problem, return_type=CArray[PauliTerm] # type:ignore[type-abstract]
33
+ )
28
34
 
29
35
 
30
36
  def grid_entangler_graph(
@@ -33,14 +39,19 @@ def grid_entangler_graph(
33
39
  grid_randomization: CBool,
34
40
  ) -> CArray[CArray[CInt]]:
35
41
  return symbolic_function(
36
- num_qubits, schmidt_rank, grid_randomization, return_type=CArray[CArray[CInt]]
42
+ num_qubits,
43
+ schmidt_rank,
44
+ grid_randomization,
45
+ return_type=CArray[CArray[CInt]], # type:ignore[type-abstract]
37
46
  )
38
47
 
39
48
 
40
49
  def hypercube_entangler_graph(
41
50
  num_qubits: CInt,
42
51
  ) -> CArray[CArray[CInt]]:
43
- return symbolic_function(num_qubits, return_type=CArray[CArray[CInt]])
52
+ return symbolic_function(
53
+ num_qubits, return_type=CArray[CArray[CInt]] # type:ignore[type-abstract]
54
+ )
44
55
 
45
56
 
46
57
  def gaussian_finance_post_process(
@@ -49,7 +60,10 @@ def gaussian_finance_post_process(
49
60
  probability: CReal,
50
61
  ) -> CReal:
51
62
  return symbolic_function(
52
- finance_model, estimation_method, probability, return_type=CReal
63
+ finance_model,
64
+ estimation_method,
65
+ probability,
66
+ return_type=CReal, # type:ignore[type-abstract]
53
67
  )
54
68
 
55
69
 
@@ -59,7 +73,10 @@ def log_normal_finance_post_process(
59
73
  probability: CReal,
60
74
  ) -> CReal:
61
75
  return symbolic_function(
62
- finance_model, estimation_method, probability, return_type=CReal
76
+ finance_model,
77
+ estimation_method,
78
+ probability,
79
+ return_type=CReal, # type:ignore[type-abstract]
63
80
  )
64
81
 
65
82
 
@@ -149,6 +149,7 @@ class Optimizer(IntEnum):
149
149
  L_BFGS_B = 3
150
150
  NELDER_MEAD = 4
151
151
  ADAM = 5
152
+ SLSQP = 6
152
153
 
153
154
 
154
155
  class Pauli(IntEnum):
@@ -64,6 +64,7 @@ CORE_LIB_DECLS = [
64
64
  inplace_prepare_state,
65
65
  inplace_prepare_amplitudes,
66
66
  single_pauli_exponent,
67
+ commuting_paulis_exponent,
67
68
  suzuki_trotter,
68
69
  qdrift,
69
70
  exponentiation_with_depth_constraint,
@@ -129,6 +130,7 @@ __all__ = [ # noqa: RUF022
129
130
  "randomized_benchmarking",
130
131
  "real_xor_constant",
131
132
  "single_pauli_exponent",
133
+ "commuting_paulis_exponent",
132
134
  "suzuki_trotter",
133
135
  "unitary",
134
136
  "RESET",
@@ -28,6 +28,30 @@ def single_pauli_exponent(
28
28
  pass
29
29
 
30
30
 
31
+ @qfunc(external=True)
32
+ def commuting_paulis_exponent(
33
+ pauli_operator: CArray[PauliTerm],
34
+ evolution_coefficient: CReal,
35
+ qbv: QArray[
36
+ QBit, Literal["get_field(get_field(pauli_operator[0], 'pauli'), 'len')"]
37
+ ],
38
+ ) -> None:
39
+ """
40
+ [Qmod core-library function]
41
+
42
+ Exponentiates the specified commutative Pauli operator.
43
+ As all the Pauli operator's terms commute, the exponential of the whole operator
44
+ is exactly the product of exponentials of each term.
45
+ Calling this funciton with a non-commutative Pauli operator will issue an error.
46
+
47
+ Args:
48
+ pauli_operator: The Pauli operator to be exponentiated.
49
+ evolution_coefficient: A global evolution coefficient multiplying the Pauli operator.
50
+ qbv: The target quantum variable of the exponentiation.
51
+ """
52
+ pass
53
+
54
+
31
55
  @qfunc(external=True)
32
56
  def suzuki_trotter(
33
57
  pauli_operator: CArray[PauliTerm],
@@ -48,7 +48,7 @@ from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QScalar, QVa
48
48
  from classiq.qmod.quantum_callable import QCallable
49
49
  from classiq.qmod.quantum_expandable import prepare_arg
50
50
  from classiq.qmod.symbolic_expr import SymbolicExpr
51
- from classiq.qmod.utilities import get_source_ref
51
+ from classiq.qmod.utilities import Statements, get_source_ref, suppress_return_value
52
52
 
53
53
  _MISSING_VALUE: Final[int] = -1
54
54
 
@@ -63,6 +63,7 @@ def allocate(out: Output[QVar]) -> None:
63
63
  pass
64
64
 
65
65
 
66
+ @suppress_return_value
66
67
  def allocate(*args: Any, **kwargs: Any) -> None:
67
68
  """
68
69
  Initialize a quantum variable to a new quantum object in the zero state:
@@ -106,6 +107,7 @@ def allocate(*args: Any, **kwargs: Any) -> None:
106
107
  )
107
108
 
108
109
 
110
+ @suppress_return_value
109
111
  def bind(
110
112
  source: Union[Input[QVar], list[Input[QVar]]],
111
113
  destination: Union[Output[QVar], list[Output[QVar]]],
@@ -125,10 +127,11 @@ def bind(
125
127
  )
126
128
 
127
129
 
130
+ @suppress_return_value
128
131
  def if_(
129
132
  condition: Union[SymbolicExpr, bool],
130
- then: Union[QCallable, Callable[[], None]],
131
- else_: Union[QCallable, Callable[[], None], int] = _MISSING_VALUE,
133
+ then: Union[QCallable, Callable[[], Statements]],
134
+ else_: Union[QCallable, Callable[[], Statements], int] = _MISSING_VALUE,
132
135
  ) -> None:
133
136
  _validate_operand(then)
134
137
  if else_ != _MISSING_VALUE:
@@ -149,10 +152,11 @@ def if_(
149
152
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(if_stmt)
150
153
 
151
154
 
155
+ @suppress_return_value
152
156
  def control(
153
157
  ctrl: Union[SymbolicExpr, QBit, QArray[QBit]],
154
- stmt_block: Union[QCallable, Callable[[], None]],
155
- else_block: Union[QCallable, Callable[[], None], None] = None,
158
+ stmt_block: Union[QCallable, Callable[[], Statements]],
159
+ else_block: Union[QCallable, Callable[[], Statements], None] = None,
156
160
  ) -> None:
157
161
  _validate_operand(stmt_block)
158
162
  assert QCallable.CURRENT_EXPANDABLE is not None
@@ -170,6 +174,7 @@ def control(
170
174
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(control_stmt)
171
175
 
172
176
 
177
+ @suppress_return_value
173
178
  def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
174
179
  """
175
180
  Initialize a scalar quantum variable using an arithmetic expression.
@@ -194,6 +199,7 @@ def assign(expression: SymbolicExpr, target_var: QScalar) -> None:
194
199
  )
195
200
 
196
201
 
202
+ @suppress_return_value
197
203
  def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
198
204
  """
199
205
  Perform an amplitude-encoding assignment operation on a quantum variable and a
@@ -216,6 +222,7 @@ def assign_amplitude(expression: SymbolicExpr, target_var: QScalar) -> None:
216
222
  )
217
223
 
218
224
 
225
+ @suppress_return_value
219
226
  def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
220
227
  """
221
228
  Add an arithmetic expression to a quantum variable.
@@ -238,6 +245,7 @@ def inplace_add(expression: SymbolicExpr, target_var: QScalar) -> None:
238
245
  )
239
246
 
240
247
 
248
+ @suppress_return_value
241
249
  def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
242
250
  """
243
251
  Bitwise-XOR a quantum variable with an arithmetic expression.
@@ -260,9 +268,10 @@ def inplace_xor(expression: SymbolicExpr, target_var: QScalar) -> None:
260
268
  )
261
269
 
262
270
 
271
+ @suppress_return_value
263
272
  def within_apply(
264
- within: Callable[[], None],
265
- apply: Callable[[], None],
273
+ within: Callable[[], Statements],
274
+ apply: Callable[[], Statements],
266
275
  ) -> None:
267
276
  _validate_operand(within)
268
277
  _validate_operand(apply)
@@ -279,7 +288,10 @@ def within_apply(
279
288
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(within_apply_stmt)
280
289
 
281
290
 
282
- def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) -> None:
291
+ @suppress_return_value
292
+ def repeat(
293
+ count: Union[SymbolicExpr, int], iteration: Callable[[int], Statements]
294
+ ) -> None:
283
295
  _validate_operand(iteration)
284
296
  assert QCallable.CURRENT_EXPANDABLE is not None
285
297
  source_ref = get_source_ref(sys._getframe(1))
@@ -310,9 +322,10 @@ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) ->
310
322
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(repeat_stmt)
311
323
 
312
324
 
325
+ @suppress_return_value
313
326
  def power(
314
327
  exponent: Union[SymbolicExpr, int],
315
- stmt_block: Union[QCallable, Callable[[], None]],
328
+ stmt_block: Union[QCallable, Callable[[], Statements]],
316
329
  ) -> None:
317
330
  _validate_operand(stmt_block)
318
331
  assert QCallable.CURRENT_EXPANDABLE is not None
@@ -327,7 +340,8 @@ def power(
327
340
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(power_stmt)
328
341
 
329
342
 
330
- def invert(stmt_block: Union[QCallable, Callable[[], None]]) -> None:
343
+ @suppress_return_value
344
+ def invert(stmt_block: Union[QCallable, Callable[[], Statements]]) -> None:
331
345
  _validate_operand(stmt_block)
332
346
  assert QCallable.CURRENT_EXPANDABLE is not None
333
347
  source_ref = get_source_ref(sys._getframe(1))
@@ -339,6 +353,7 @@ def invert(stmt_block: Union[QCallable, Callable[[], None]]) -> None:
339
353
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(invert_stmt)
340
354
 
341
355
 
356
+ @suppress_return_value
342
357
  def phase(expr: SymbolicExpr, theta: float = 1.0) -> None:
343
358
  assert QCallable.CURRENT_EXPANDABLE is not None
344
359
  source_ref = get_source_ref(sys._getframe(1))
@@ -402,7 +417,7 @@ def _get_operand_hint(
402
417
 
403
418
 
404
419
  def _operand_to_body(
405
- callable_: Union[QCallable, Callable[[], None]], param_name: str
420
+ callable_: Union[QCallable, Callable[[], Statements]], param_name: str
406
421
  ) -> StatementBlock:
407
422
  op_name = sys._getframe(1).f_code.co_name
408
423
  if (
classiq/qmod/cparam.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import sys
2
+ from abc import ABC, abstractmethod
2
3
  from typing import ( # type: ignore[attr-defined]
3
4
  TYPE_CHECKING,
4
5
  Any,
@@ -9,6 +10,8 @@ from typing import ( # type: ignore[attr-defined]
9
10
 
10
11
  from typing_extensions import ParamSpec
11
12
 
13
+ from classiq.interface.exceptions import ClassiqValueError
14
+
12
15
  from classiq.qmod.symbolic_expr import Symbolic, SymbolicExpr
13
16
 
14
17
  if TYPE_CHECKING:
@@ -21,18 +24,34 @@ else:
21
24
 
22
25
  class CParam(SymbolicSuperclass):
23
26
  def __init__(self, expr: str) -> None:
24
- super().__init__(expr, False)
27
+ super().__init__(expr, is_quantum=False)
28
+
29
+
30
+ class CParamAbstract(ABC, CParam):
31
+
32
+ def __new__(cls, *args: Any, **kwargs: Any) -> "CParamAbstract":
33
+ raise ClassiqValueError(
34
+ f"{cls.__name__} is a Qmod type hint for a classical parameter and it cannot be instantiated. "
35
+ f"Use regular Pythonic values as arguments instead. "
36
+ f"Example:\n\n"
37
+ f"def foo(val: {cls.__name__}) -> None: ...\n\n"
38
+ f"foo({_EXAMPLE_VALUES[cls.__name__]}) # Correct\n"
39
+ )
25
40
 
41
+ @abstractmethod
42
+ def __init__(self) -> None:
43
+ pass
26
44
 
27
- class CInt(CParam):
45
+
46
+ class CInt(CParamAbstract):
28
47
  pass
29
48
 
30
49
 
31
- class CReal(CParam):
50
+ class CReal(CParamAbstract):
32
51
  pass
33
52
 
34
53
 
35
- class CBool(CParam):
54
+ class CBool(CParamAbstract):
36
55
  pass
37
56
 
38
57
 
@@ -47,7 +66,7 @@ class ArrayBase(Generic[_P]):
47
66
  return _GenericAlias(cls, args)
48
67
 
49
68
 
50
- class CArray(CParam, ArrayBase[_P]):
69
+ class CArray(CParamAbstract, ArrayBase[_P]):
51
70
  if TYPE_CHECKING:
52
71
 
53
72
  @property
@@ -62,3 +81,11 @@ Array = CArray
62
81
  class CParamScalar(CParam, SymbolicExpr):
63
82
  def __hash__(self) -> int:
64
83
  return hash(str(self))
84
+
85
+
86
+ _EXAMPLE_VALUES: dict[str, Any] = {
87
+ CInt.__name__: 1,
88
+ CReal.__name__: 1.0,
89
+ CBool.__name__: True,
90
+ CArray.__name__: [1, 2],
91
+ }
@@ -30,16 +30,22 @@ CARRAY_ERROR_MESSAGE = (
30
30
 
31
31
  class PythonClassicalType:
32
32
  def convert(self, py_type: type) -> Optional[ConcreteClassicalType]:
33
- if py_type is int or py_type is CInt:
33
+ if py_type is int:
34
+ return Integer().set_generative()
35
+ elif py_type is CInt:
34
36
  return Integer()
35
- elif py_type in (float, complex) or py_type is CReal:
37
+ elif py_type in (float, complex):
38
+ return Real().set_generative()
39
+ elif py_type is CReal:
36
40
  return Real()
37
- elif py_type is bool or py_type is CBool:
41
+ elif py_type is bool:
42
+ return Bool().set_generative()
43
+ elif py_type is CBool:
38
44
  return Bool()
39
45
  elif get_origin(py_type) is list:
40
46
  element_type = self.convert(get_args(py_type)[0])
41
47
  if element_type is not None:
42
- return ClassicalList(element_type=element_type)
48
+ return ClassicalList(element_type=element_type).set_generative()
43
49
  elif get_origin(py_type) is CArray:
44
50
  array_args = version_portable_get_args(py_type)
45
51
  if len(array_args) == 1:
@@ -21,7 +21,7 @@ from classiq.interface.model.quantum_type import QuantumType
21
21
  from classiq.interface.source_reference import SourceReference
22
22
 
23
23
  from classiq.qmod.cparam import CInt
24
- from classiq.qmod.utilities import get_source_ref
24
+ from classiq.qmod.utilities import get_source_ref, suppress_return_value
25
25
 
26
26
  if TYPE_CHECKING:
27
27
  from classiq.qmod.quantum_expandable import QTerminalCallable
@@ -48,6 +48,7 @@ class QCallable(Generic[P], ABC):
48
48
  CURRENT_EXPANDABLE: ClassVar[Optional[QExpandableInterface]] = None
49
49
  FRAME_DEPTH = 1
50
50
 
51
+ @suppress_return_value
51
52
  def __call__(self, *args: Any, **kwargs: Any) -> None:
52
53
  assert QCallable.CURRENT_EXPANDABLE is not None
53
54
  source_ref = get_source_ref(sys._getframe(self.FRAME_DEPTH))
@@ -24,10 +24,11 @@ from classiq.interface.model.quantum_function_declaration import (
24
24
  )
25
25
 
26
26
  from classiq.qmod.classical_function import CFunc
27
+ from classiq.qmod.cparam import CParamAbstract
27
28
  from classiq.qmod.declaration_inferrer import infer_func_decl
28
29
  from classiq.qmod.generative import set_frontend_interpreter
29
30
  from classiq.qmod.qmod_constant import QConstant
30
- from classiq.qmod.qmod_parameter import CArray, CParam
31
+ from classiq.qmod.qmod_parameter import CArray
31
32
  from classiq.qmod.qmod_variable import QVar
32
33
  from classiq.qmod.quantum_callable import QCallable, QCallableList
33
34
  from classiq.qmod.quantum_expandable import QExpandable, QTerminalCallable
@@ -308,7 +309,7 @@ def _validate_no_gen_params(annotations: dict[str, Any]) -> None:
308
309
  for name, annotation in annotations.items()
309
310
  if not (
310
311
  name == "return"
311
- or (isclass(annotation) and issubclass(annotation, CParam))
312
+ or (isclass(annotation) and issubclass(annotation, CParamAbstract))
312
313
  or (isclass(annotation) and is_dataclass(annotation))
313
314
  or (isclass(annotation) and isinstance(annotation, EnumMeta))
314
315
  or get_origin(annotation) is CArray