classiq 0.54.0__py3-none-any.whl → 0.56.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 (56) hide show
  1. classiq/interface/_version.py +1 -1
  2. classiq/interface/debug_info/debug_info.py +11 -0
  3. classiq/interface/executor/result.py +0 -3
  4. classiq/interface/generator/functions/builtins/internal_operators.py +9 -1
  5. classiq/interface/generator/generated_circuit_data.py +0 -1
  6. classiq/interface/generator/model/preferences/preferences.py +4 -0
  7. classiq/interface/generator/types/compilation_metadata.py +5 -0
  8. classiq/interface/generator/visitor.py +13 -1
  9. classiq/interface/ide/visual_model.py +5 -1
  10. classiq/interface/interface_version.py +1 -1
  11. classiq/interface/model/control.py +22 -1
  12. classiq/interface/model/handle_binding.py +28 -0
  13. classiq/interface/model/model.py +4 -0
  14. classiq/interface/model/native_function_definition.py +1 -1
  15. classiq/interface/model/quantum_expressions/arithmetic_operation.py +2 -26
  16. classiq/interface/model/quantum_statement.py +6 -0
  17. classiq/model_expansions/capturing/mangling_utils.py +22 -0
  18. classiq/model_expansions/capturing/propagated_var_stack.py +36 -25
  19. classiq/model_expansions/closure.py +77 -12
  20. classiq/model_expansions/function_builder.py +9 -10
  21. classiq/model_expansions/generative_functions.py +2 -2
  22. classiq/model_expansions/interpreter.py +29 -26
  23. classiq/model_expansions/quantum_operations/control.py +114 -29
  24. classiq/model_expansions/quantum_operations/emitter.py +37 -11
  25. classiq/model_expansions/quantum_operations/expression_operation.py +80 -18
  26. classiq/model_expansions/quantum_operations/power.py +5 -0
  27. classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +7 -37
  28. classiq/model_expansions/quantum_operations/quantum_function_call.py +2 -32
  29. classiq/model_expansions/quantum_operations/repeat.py +5 -0
  30. classiq/model_expansions/quantum_operations/within_apply.py +0 -16
  31. classiq/model_expansions/scope_initialization.py +2 -3
  32. classiq/qmod/builtins/functions/arithmetic.py +0 -2
  33. classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +0 -12
  34. classiq/qmod/builtins/functions/exponentiation.py +0 -6
  35. classiq/qmod/builtins/functions/grover.py +0 -17
  36. classiq/qmod/builtins/functions/linear_pauli_rotation.py +0 -5
  37. classiq/qmod/builtins/functions/modular_exponentiation.py +0 -3
  38. classiq/qmod/builtins/functions/qaoa_penalty.py +0 -8
  39. classiq/qmod/builtins/functions/qft_functions.py +0 -3
  40. classiq/qmod/builtins/functions/qpe.py +0 -6
  41. classiq/qmod/builtins/functions/qsvt.py +0 -12
  42. classiq/qmod/builtins/functions/standard_gates.py +0 -88
  43. classiq/qmod/builtins/functions/state_preparation.py +7 -15
  44. classiq/qmod/builtins/functions/swap_test.py +0 -3
  45. classiq/qmod/builtins/operations.py +152 -17
  46. classiq/qmod/create_model_function.py +10 -12
  47. classiq/qmod/model_state_container.py +5 -1
  48. classiq/qmod/native/pretty_printer.py +6 -1
  49. classiq/qmod/pretty_print/pretty_printer.py +25 -11
  50. classiq/qmod/qmod_constant.py +31 -3
  51. classiq/qmod/quantum_function.py +25 -19
  52. classiq/qmod/synthesize_separately.py +1 -2
  53. {classiq-0.54.0.dist-info → classiq-0.56.0.dist-info}/METADATA +2 -3
  54. {classiq-0.54.0.dist-info → classiq-0.56.0.dist-info}/RECORD +55 -55
  55. classiq/model_expansions/call_to_model_converter.py +0 -190
  56. {classiq-0.54.0.dist-info → classiq-0.56.0.dist-info}/WHEEL +0 -0
@@ -1,7 +1,7 @@
1
1
  import ast
2
2
  from abc import abstractmethod
3
3
  from itertools import chain
4
- from typing import TYPE_CHECKING, TypeVar
4
+ from typing import TYPE_CHECKING, TypeVar, Union
5
5
 
6
6
  from classiq.interface.exceptions import (
7
7
  ClassiqExpansionError,
@@ -12,7 +12,9 @@ from classiq.interface.generator.expressions.evaluated_expression import (
12
12
  )
13
13
  from classiq.interface.generator.expressions.expression import Expression
14
14
  from classiq.interface.generator.functions.type_name import TypeName
15
+ from classiq.interface.generator.visitor import NodeType, Transformer
15
16
  from classiq.interface.model.bind_operation import BindOperation
17
+ from classiq.interface.model.control import Control
16
18
  from classiq.interface.model.handle_binding import (
17
19
  FieldHandleBinding,
18
20
  HandleBinding,
@@ -20,6 +22,7 @@ from classiq.interface.model.handle_binding import (
20
22
  SubscriptHandleBinding,
21
23
  )
22
24
  from classiq.interface.model.quantum_expressions.quantum_expression import (
25
+ QuantumAssignmentOperation,
23
26
  QuantumExpressionOperation,
24
27
  )
25
28
  from classiq.interface.model.quantum_type import (
@@ -38,6 +41,7 @@ from classiq.model_expansions.scope import QuantumSymbol
38
41
  from classiq.model_expansions.visitors.variable_references import VarRefCollector
39
42
 
40
43
  ExpressionOperationT = TypeVar("ExpressionOperationT", bound=QuantumExpressionOperation)
44
+ AST_NODE = TypeVar("AST_NODE", bound=NodeType)
41
45
 
42
46
 
43
47
  class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
@@ -49,7 +53,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
49
53
  self,
50
54
  op: ExpressionOperationT,
51
55
  expression: Expression,
52
- symbols_to_split: list[QuantumSymbol],
56
+ symbols_to_split: dict[QuantumSymbol, set[HandleBinding]],
53
57
  ) -> None:
54
58
  symbols_parts, bind_ops = self._get_bind_ops(symbols_to_split)
55
59
 
@@ -79,8 +83,8 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
79
83
  )
80
84
  )
81
85
 
82
- @staticmethod
83
86
  def _get_updated_op_split_symbols(
87
+ self,
84
88
  op: ExpressionOperationT,
85
89
  symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
86
90
  ) -> ExpressionOperationT:
@@ -109,11 +113,10 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
109
113
  )
110
114
  return new_expr
111
115
 
112
- @staticmethod
113
- def _check_all_handles_were_replaced(new_expr_str: str) -> None:
116
+ def _check_all_handles_were_replaced(self, new_expr_str: str) -> None:
114
117
  vrc = VarRefCollector(ignore_duplicated_handles=True)
115
118
  vrc.visit(ast.parse(new_expr_str))
116
- for handle in vrc.var_handles:
119
+ for handle in self._get_handles(vrc):
117
120
  if isinstance(
118
121
  handle,
119
122
  (SubscriptHandleBinding, SlicedHandleBinding, FieldHandleBinding),
@@ -122,12 +125,12 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
122
125
 
123
126
  def _get_bind_ops(
124
127
  self,
125
- symbols_to_split: list[QuantumSymbol],
128
+ symbols_to_split: dict[QuantumSymbol, set[HandleBinding]],
126
129
  ) -> tuple[list[list[tuple[QuantumSymbol, str]]], list[BindOperation]]:
127
130
  bind_ops = []
128
131
  symbols_parts = []
129
- for symbol in symbols_to_split:
130
- symbol_parts = self._get_symbol_parts(symbol)
132
+ for symbol, target_parts in symbols_to_split.items():
133
+ symbol_parts = self._get_symbol_parts(symbol, target_parts)
131
134
  symbols_parts.append(symbol_parts)
132
135
  bind_ops.append(
133
136
  BindOperation(
@@ -141,11 +144,14 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
141
144
  return symbols_parts, bind_ops
142
145
 
143
146
  def _get_symbol_parts(
144
- self, symbol: QuantumSymbol
147
+ self, symbol: QuantumSymbol, target_parts: set[HandleBinding]
145
148
  ) -> list[tuple[QuantumSymbol, str]]:
146
149
  quantum_type = symbol.quantum_type
147
150
 
148
- if isinstance(quantum_type, (QuantumBit, QuantumNumeric)):
151
+ if all(
152
+ symbol.handle == target_part or symbol.handle not in target_part.prefixes()
153
+ for target_part in target_parts
154
+ ) or isinstance(quantum_type, (QuantumBit, QuantumNumeric)):
149
155
  return [
150
156
  (
151
157
  symbol,
@@ -161,7 +167,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
161
167
  )
162
168
  return list(
163
169
  chain.from_iterable(
164
- self._get_symbol_parts(symbol[idx])
170
+ self._get_symbol_parts(symbol[idx], target_parts)
165
171
  for idx in range(quantum_type.length_value)
166
172
  )
167
173
  )
@@ -171,27 +177,33 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
171
177
 
172
178
  return list(
173
179
  chain.from_iterable(
174
- self._get_symbol_parts(field_symbol)
180
+ self._get_symbol_parts(field_symbol, target_parts)
175
181
  for field_symbol in symbol.fields.values()
176
182
  )
177
183
  )
178
184
 
179
- def _get_symbols_to_split(self, expression: Expression) -> list[QuantumSymbol]:
185
+ def _get_symbols_to_split(
186
+ self, expression: Expression
187
+ ) -> dict[QuantumSymbol, set[HandleBinding]]:
180
188
  vrc = VarRefCollector(ignore_duplicated_handles=True)
181
189
  vrc.visit(ast.parse(expression.expr))
182
190
  symbol_names_to_split = dict.fromkeys(
183
191
  handle.name
184
- for handle in vrc.var_handles
192
+ for handle in self._get_handles(vrc)
185
193
  if isinstance(handle, (SubscriptHandleBinding, FieldHandleBinding))
186
194
  )
187
- return [
188
- symbol
195
+ return {
196
+ symbol: {
197
+ handle.collapse()
198
+ for handle in vrc.var_handles
199
+ if handle.name == symbol.handle.name
200
+ }
189
201
  for symbol_name in symbol_names_to_split
190
202
  if isinstance(
191
203
  symbol := self._current_scope[symbol_name].value,
192
204
  QuantumSymbol,
193
205
  )
194
- ]
206
+ }
195
207
 
196
208
  def _evaluate_op_expression(self, op: ExpressionOperationT) -> Expression:
197
209
  return self._evaluate_expression(op.expression)
@@ -214,3 +226,53 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
214
226
  self._machine_precision,
215
227
  )
216
228
  return op_with_evaluated_types
229
+
230
+ @staticmethod
231
+ def _all_vars_boolean(op: QuantumExpressionOperation) -> bool:
232
+ if not all(
233
+ var_type.has_size_in_bits and var_type.size_in_bits == 1
234
+ for var_type in op.var_types.values()
235
+ ):
236
+ return False
237
+ return not any(
238
+ isinstance(var_type, QuantumNumeric)
239
+ and (var_type.sign_value or var_type.fraction_digits_value > 0)
240
+ for var_type in op.var_types.values()
241
+ )
242
+
243
+ @staticmethod
244
+ def _is_res_boolean(op: Union[QuantumAssignmentOperation, Control]) -> bool:
245
+ if not (op.result_type.has_size_in_bits and op.result_type.size_in_bits == 1):
246
+ return False
247
+ return not (
248
+ isinstance(op.result_type, QuantumNumeric)
249
+ and (op.result_type.sign_value or op.result_type.fraction_digits_value > 0)
250
+ )
251
+
252
+ def _get_handles(self, collector: VarRefCollector) -> list[HandleBinding]:
253
+ return [
254
+ handle
255
+ for handle in collector.var_handles
256
+ if isinstance(self._interpreter.evaluate(handle.name).value, QuantumSymbol)
257
+ ]
258
+
259
+ def _rewrite(
260
+ self,
261
+ subject: AST_NODE,
262
+ symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
263
+ ) -> AST_NODE:
264
+ class ReplaceSplitVars(Transformer):
265
+ @staticmethod
266
+ def visit_HandleBinding(handle: HandleBinding) -> HandleBinding:
267
+ handle = handle.collapse()
268
+ for handle_to_replace, replacement in symbol_mapping.items():
269
+ handle = handle.replace_prefix(
270
+ handle_to_replace, HandleBinding(name=replacement[0])
271
+ )
272
+ return handle
273
+
274
+ @staticmethod
275
+ def visit_Expression(expr: Expression) -> Expression:
276
+ return self._update_op_expression(symbol_mapping, expr)
277
+
278
+ return ReplaceSplitVars().visit(subject)
@@ -2,6 +2,7 @@ from typing import Union
2
2
 
3
3
  import sympy
4
4
 
5
+ from classiq.interface.exceptions import ClassiqExpansionError
5
6
  from classiq.interface.generator.expressions.evaluated_expression import (
6
7
  EvaluatedExpression,
7
8
  )
@@ -72,4 +73,8 @@ class PowerEmitter(Emitter[Power]):
72
73
 
73
74
  def _get_power_value(self) -> Union[int, sympy.Basic]:
74
75
  power_value = self._interpreter.evaluate(self._power.power).value
76
+ if isinstance(power_value, int) and power_value < 0:
77
+ raise ClassiqExpansionError(
78
+ f"power exponent must be non-negative, got {power_value}"
79
+ )
75
80
  return power_value
@@ -29,6 +29,7 @@ from classiq.interface.model.variable_declaration_statement import (
29
29
  )
30
30
  from classiq.interface.model.within_apply_operation import WithinApply
31
31
 
32
+ from classiq.model_expansions.capturing.mangling_utils import demangle_handle
32
33
  from classiq.model_expansions.evaluators.quantum_type_utils import copy_type_information
33
34
  from classiq.model_expansions.quantum_operations.expression_operation import (
34
35
  ExpressionOperationEmitter,
@@ -101,7 +102,7 @@ class QuantumAssignmentOperationEmitter(
101
102
  if (
102
103
  op.operation_kind != ArithmeticOperationKind.InplaceXor
103
104
  or op.result_type.size_in_bits > 1
104
- or not _is_res_boolean(op)
105
+ or not self._is_res_boolean(op)
105
106
  or target.quantum_type.size_in_bits > 1
106
107
  or _is_constant(expression.expr)
107
108
  ):
@@ -141,7 +142,8 @@ class QuantumAssignmentOperationEmitter(
141
142
  ArithmeticOperationKind.Assignment,
142
143
  ArithmeticOperationKind.InplaceXor,
143
144
  )
144
- or not _all_vars_boolean(op)
145
+ or not self._all_vars_boolean(op)
146
+ or not self._is_res_boolean(op)
145
147
  ):
146
148
  return op, expression, False
147
149
  optimizer = BooleanExpressionOptimizer()
@@ -227,50 +229,18 @@ class QuantumAssignmentOperationEmitter(
227
229
  self._interpreter.emit_statement(allocate_call)
228
230
  return True
229
231
 
230
- @staticmethod
231
232
  def _get_updated_op_split_symbols(
233
+ self,
232
234
  op: QuantumAssignmentOperation,
233
235
  symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
234
236
  ) -> QuantumAssignmentOperation:
235
- if op.result_var not in symbol_mapping:
236
- return op
237
- handle_str, quantum_type = symbol_mapping[op.result_var]
238
- if handle_str in op.expression.expr:
239
- raise ClassiqExpansionError(
240
- HANDLE_ERROR_MESSAGE.format(handle_str=str(op.result_var))
241
- )
242
- new_result_handle = HandleBinding(name=handle_str)
243
237
  return op.model_copy(
244
- update=dict(result_var=new_result_handle, _result_type=quantum_type)
238
+ update=dict(result_var=self._rewrite(op.result_var, symbol_mapping))
245
239
  )
246
240
 
247
241
 
248
242
  def _validate_naive_inplace_handles(qe: ArithmeticOperation) -> None:
249
243
  if qe.result_var in qe.var_handles:
250
244
  raise ClassiqExpansionError(
251
- HANDLE_ERROR_MESSAGE.format(handle_str=str(qe.result_var))
245
+ HANDLE_ERROR_MESSAGE.format(handle_str=str(demangle_handle(qe.result_var)))
252
246
  )
253
-
254
-
255
- def _all_vars_boolean(op: ArithmeticOperation) -> bool:
256
- if not all(
257
- var_type.has_size_in_bits and var_type.size_in_bits == 1
258
- for var_type in op.var_types.values()
259
- ):
260
- return False
261
- if any(
262
- isinstance(var_type, QuantumNumeric)
263
- and (var_type.sign_value or var_type.fraction_digits_value > 0)
264
- for var_type in op.var_types.values()
265
- ):
266
- return False
267
- return _is_res_boolean(op)
268
-
269
-
270
- def _is_res_boolean(op: ArithmeticOperation) -> bool:
271
- if not (op.result_type.has_size_in_bits and op.result_type.size_in_bits == 1):
272
- return False
273
- return not (
274
- isinstance(op.result_type, QuantumNumeric)
275
- and (op.result_type.sign_value or op.result_type.fraction_digits_value > 0)
276
- )
@@ -2,10 +2,6 @@ from typing import TYPE_CHECKING
2
2
 
3
3
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
4
4
 
5
- from classiq.model_expansions.call_to_model_converter import (
6
- BlockFunctionInfo,
7
- CallToModelConverter,
8
- )
9
5
  from classiq.model_expansions.closure import FunctionClosure
10
6
  from classiq.model_expansions.quantum_operations.emitter import Emitter
11
7
  from classiq.qmod.semantics.error_manager import ErrorManager
@@ -18,37 +14,11 @@ class QuantumFunctionCallEmitter(Emitter[QuantumFunctionCall]):
18
14
  def __init__(self, interpreter: "Interpreter") -> None:
19
15
  super().__init__(interpreter)
20
16
  self._model = self._interpreter._model
21
- self._synthesized_separately_blocks = (
22
- self._interpreter._synthesized_separately_blocks
23
- )
24
17
 
25
18
  def emit(self, call: QuantumFunctionCall, /) -> None:
26
- function: FunctionClosure = self._interpreter.evaluate(call.function).as_type(
27
- FunctionClosure
28
- )
19
+ function = self._interpreter.evaluate(call.function).as_type(FunctionClosure)
29
20
  args = call.positional_args
30
21
  with ErrorManager().call(
31
22
  function.name
32
23
  ), function.scope.freeze(), self._propagated_var_stack.capture_variables(call):
33
- new_call = self._emit_quantum_function_call(function, args)
34
- if function.synthesis_data.should_synthesize_separately:
35
- interpreted_call_converter = CallToModelConverter(
36
- call,
37
- function.positional_arg_declarations,
38
- function.scope.data,
39
- self._model,
40
- )
41
- self._update_synthesized_separately_models(
42
- interpreted_call_converter, new_call.func_name
43
- )
44
-
45
- def _update_synthesized_separately_models(
46
- self, call_converter: CallToModelConverter, call_name: str
47
- ) -> None:
48
- synthesized_separately_blocks = self._synthesized_separately_blocks
49
- block_id = call_converter.block_id
50
- block_function = synthesized_separately_blocks.get(block_id)
51
- if block_function is None:
52
- block_function = BlockFunctionInfo.from_call_converter(call_converter)
53
- synthesized_separately_blocks[block_id] = block_function
54
- block_function.calls.add(call_name)
24
+ self._emit_quantum_function_call(function, args)
@@ -1,3 +1,4 @@
1
+ from classiq.interface.exceptions import ClassiqExpansionError
1
2
  from classiq.interface.generator.expressions.expression import Expression
2
3
  from classiq.interface.generator.functions.builtins.internal_operators import (
3
4
  REPEAT_OPERATOR_NAME,
@@ -17,6 +18,10 @@ from classiq.qmod.quantum_function import GenerativeQFunc
17
18
  class RepeatEmitter(Emitter[Repeat]):
18
19
  def emit(self, repeat: Repeat, /) -> None:
19
20
  count = self._interpreter.evaluate(repeat.count).as_type(int)
21
+ if count < 0:
22
+ raise ClassiqExpansionError(
23
+ f"repeat count must be non-negative, got {count}"
24
+ )
20
25
  for i in range(count):
21
26
  with self._propagated_var_stack.capture_variables(repeat):
22
27
  self._emit_propagated(repeat, i)
@@ -1,5 +1,4 @@
1
1
  from classiq.interface.generator.functions.builtins.internal_operators import (
2
- COMPUTE_OPERATOR_NAME,
3
2
  WITHIN_APPLY_NAME,
4
3
  )
5
4
  from classiq.interface.model.within_apply_operation import WithinApply
@@ -26,10 +25,6 @@ class WithinApplyEmitter(Emitter[WithinApply]):
26
25
  }
27
26
  )
28
27
 
29
- if self._should_wrap(within_apply.compute):
30
- self._emit_wrapped(within_apply)
31
- return
32
-
33
28
  self._emit_as_operation(within_apply)
34
29
 
35
30
  def _emit_as_operation(self, within_apply: WithinApply) -> None:
@@ -46,14 +41,3 @@ class WithinApplyEmitter(Emitter[WithinApply]):
46
41
  source_ref=within_apply.source_ref,
47
42
  )
48
43
  )
49
-
50
- def _emit_wrapped(self, within_apply: WithinApply) -> None:
51
- wrapped_compute = self._create_expanded_wrapping_function(
52
- COMPUTE_OPERATOR_NAME, within_apply.compute
53
- )
54
- wrapped_within_apply = WithinApply(
55
- compute=[wrapped_compute],
56
- action=within_apply.action,
57
- source_ref=within_apply.source_ref,
58
- )
59
- self._builder.emit_statement(wrapped_within_apply)
@@ -43,7 +43,7 @@ def get_main_renamer(
43
43
  return ExpressionRenamer(var_mapping={})
44
44
 
45
45
 
46
- def _add_constants_to_scope(constants: list[Constant], scope: Scope) -> None:
46
+ def add_constants_to_scope(constants: list[Constant], scope: Scope) -> None:
47
47
  for constant in constants:
48
48
  scope[constant.name] = Evaluated(
49
49
  value=evaluate_classical_expression(constant.value, scope).value
@@ -60,7 +60,6 @@ def _add_functions_to_scope(
60
60
  positional_arg_declarations=function.positional_arg_declarations,
61
61
  body=function.body,
62
62
  scope=Scope(parent=scope),
63
- synthesis_data=function.synthesis_data,
64
63
  )
65
64
  )
66
65
 
@@ -143,5 +142,5 @@ def init_top_level_scope(
143
142
  ) -> None:
144
143
  _add_functions_to_scope(model.functions, scope)
145
144
  _add_generative_functions_to_scope(generative_functions, scope)
146
- _add_constants_to_scope(model.constants, scope)
145
+ add_constants_to_scope(model.constants, scope)
147
146
  _init_builtins_scope(scope)
@@ -23,8 +23,6 @@ def unitary(
23
23
  Args:
24
24
  elements: A 2d array of complex numbers representing the unitary matrix. This matrix must be unitary.
25
25
  target: The quantum state to apply the unitary on. Should be of corresponding size.
26
-
27
- Links: [Reference Manual](https://docs.classiq.io/qmod/builtins/functions/standard_gates/unitary)
28
26
  """
29
27
  pass
30
28
 
@@ -105,9 +105,6 @@ def qct_qst_type1(x: QArray[QBit]) -> None:
105
105
 
106
106
  Args:
107
107
  x: The qubit array to apply the transform to.
108
-
109
- Links:
110
- - [Quantum Sine and Cosine Transforms](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/open-library-functions/qct_qst/qct_qst/)
111
108
  """
112
109
  within_apply(lambda: _t_operator(x), lambda: qft(x))
113
110
 
@@ -134,9 +131,6 @@ def qct_qst_type2(x: QArray[QBit], q: QBit) -> None:
134
131
  Args:
135
132
  x: The LSB part of the qubit array to apply the transform to.
136
133
  q: The MSB of the qubit array to apply the transform to.
137
-
138
- Links:
139
- - [Quantum Sine and Cosine Transforms](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/open-library-functions/qct_qst/qct_qst/)
140
134
  """
141
135
  extended_state: QArray = QArray("extended_state")
142
136
  _vn_operator(x, q)
@@ -156,9 +150,6 @@ def qct_type2(x: QArray[QBit]) -> None:
156
150
 
157
151
  Args:
158
152
  x: The qubit array to apply the transform to.
159
-
160
- Links:
161
- - [Quantum Sine and Cosine Transforms](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/open-library-functions/qct_qst/qct_qst/)
162
153
  """
163
154
  q = QBit("q")
164
155
  within_apply(lambda: allocate(1, q), lambda: qct_qst_type2(x, q))
@@ -174,9 +165,6 @@ def qst_type2(x: QArray[QBit]) -> None:
174
165
 
175
166
  Args:
176
167
  x: The qubit array to apply the transform to.
177
-
178
- Links:
179
- - [Quantum Sine and Cosine Transforms](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/open-library-functions/qct_qst/qct_qst/)
180
168
  """
181
169
  q = QBit("q")
182
170
  within_apply(
@@ -45,8 +45,6 @@ def suzuki_trotter(
45
45
  The Suzuki-Trotter decomposition of a given order nullifies the error of the Taylor series expansion of the product of exponentials up to that order.
46
46
  The error of a Suzuki-Trotter decomposition decreases as the order and number of repetitions increase.
47
47
 
48
- See [N. Hatano and M. Suzuki, Finding Exponential Product Formulas of Higher Orders (2005)](https://arxiv.org/abs/math-ph/0506007).
49
-
50
48
  Args:
51
49
  pauli_operator: The Pauli operator to be exponentiated.
52
50
  evolution_coefficient: A global evolution coefficient multiplying the Pauli operator.
@@ -73,8 +71,6 @@ def qdrift(
73
71
  The QDrift method randomizes the order of the operators in the product of exponentials to stochastically reduce the error of the approximation.
74
72
  The error of the QDrift method decreases as the number of QDrift steps increases.
75
73
 
76
- See [E. Campbell, Random Compiler for Fast Hamiltonian Simulation (2019)](https://arxiv.org/abs/1811.08017).
77
-
78
74
  Args:
79
75
  pauli_operator: The Pauli operator to be exponentiated.
80
76
  evolution_coefficient: A global evolution coefficient multiplying the Pauli operator.
@@ -100,8 +96,6 @@ def exponentiation_with_depth_constraint(
100
96
  The Suzuki-Trotter decomposition is a method for approximating the exponential of a sum of operators by a product of exponentials of each operator.
101
97
  This function automatically determines the order and number of repetitions of the Suzuki-Trotter decomposition to minimize the error given a depth constraint.
102
98
 
103
- See [A. M. Childs et al., Toward the first quantum simulation with quantum speedup (2017)](https://arxiv.org/abs/1711.10980).
104
-
105
99
  Args:
106
100
  pauli_operator: The Pauli operator to be exponentiated.
107
101
  evolution_coefficient: A global coefficient multiplying the Pauli operator.
@@ -39,11 +39,6 @@ def phase_oracle(
39
39
  Args:
40
40
  predicate: A predicate function that takes a QArray of QBits and sets a single QBit |1> if the predicate is true, and |0> otherwise.
41
41
  target: The target QArray of QBits to apply the phase oracle to.
42
-
43
- Usage Examples:
44
- [Grover Algorithm](https://docs.classiq.io/latest/explore/functions/qmod_library_reference/classiq_open_library/grover_operator/grover_operator/)
45
-
46
- [Hidden shift](https://docs.classiq.io/latest/explore/algorithms/algebraic/hidden_shift/hidden_shift/)
47
42
  """
48
43
  aux = QBit("aux")
49
44
  within_apply(
@@ -125,18 +120,10 @@ def grover_operator(
125
120
  where $S_{\\psi_1}$ is a reflection about marked states, and $S_{\\psi_0}$ is a reflection
126
121
  about a given state defined by $|\\psi_0\rangle = A|0\rangle$.
127
122
 
128
-
129
123
  Args:
130
124
  oracle: A unitary operator which adds a phase of (-1) to marked states.
131
125
  space_transform: The operator which creates $|\\psi_0\rangle$, the initial state, used by the diffuser to reflect about it.
132
126
  packed_vars: The state to which to apply the grover operator.
133
-
134
-
135
- For further reading, see:
136
-
137
- - [The Grover Operator notebook](../explore/functions/qmod_library_reference/classiq_open_library/grover_operator/grover_operator/)
138
- - [Wikipedia page](https://en.wikipedia.org/wiki/Grover%27s_algorithm).
139
-
140
127
  """
141
128
  oracle(packed_vars)
142
129
  grover_diffuser(lambda qba: space_transform(qba), packed_vars)
@@ -158,10 +145,6 @@ def grover_search(
158
145
  packed_vars: Packed form of the variable to apply the grover operator on.
159
146
 
160
147
  Returns: None
161
-
162
- Links:
163
- [Grover Algorithm](https://docs.classiq.io/latest/explore/functions/qmod_library_reference/classiq_open_library/grover_operator/grover_operator/)
164
-
165
148
  """
166
149
  hadamard_transform(packed_vars)
167
150
  power(
@@ -61,11 +61,6 @@ def linear_pauli_rotations(
61
61
  q: List of indicator qubits for each of the given Pauli bases.
62
62
 
63
63
  Notice that bases, slopes, offset and q should be of the same size.
64
-
65
-
66
-
67
- Links:
68
- [linear_pauli_rotations](https://docs.classiq.io/latest/explore/functions/qmod_library_reference/classiq_open_library/linear_pauli_rotations/linear_pauli_rotations)
69
64
  """
70
65
  repeat(
71
66
  q.len,
@@ -186,9 +186,6 @@ def modular_exp(n: CInt, a: CInt, x: QArray[QBit], power: QArray[QBit]) -> None:
186
186
  a: The base of the exponentiation. Should be non-negative.
187
187
  x: A quantum number that multiplies the modular exponentiation and holds the output. It should be at least the size of $\\lceil \\log(n) \rceil$.
188
188
  power: The power of the exponentiation.
189
-
190
- Usage Example:
191
- [Modular Exponentiation](https://docs.classiq.io/latest/explore/functions/function_usage_examples/arithmetic/modular_exp/modular_exp_example)
192
189
  """
193
190
  repeat(
194
191
  count=power.len,
@@ -17,9 +17,6 @@ def qaoa_mixer_layer(b: CReal, target: QArray[QBit]) -> None:
17
17
  The mixer layer is a sequence of `X` gates applied to each qubit in the target quantum
18
18
  array variable.
19
19
 
20
- Please refer to the [QAOA mixer tutorial](https://docs.classiq.io/latest/reference-manual/built-in-algorithms/combinatorial-optimization/problem-solving/) for an example
21
-
22
-
23
20
  Args:
24
21
  b: The rotation parameter for the mixer layer.
25
22
  target: The target quantum array.
@@ -40,7 +37,6 @@ def qaoa_cost_layer(
40
37
  The cost layer represents the primary objective that the QAOA algorithm seeks to optimize, such as
41
38
  minimizing energy or maximizing profit, depending on the application.
42
39
 
43
- For more details on defining cost functions in QAOA models using Pyomo, see: [Problem Formulation](https://docs.classiq.io/latest/reference-manual/built-in-algorithms/combinatorial-optimization/)
44
40
  Args:
45
41
  g: The rotation parameter for the cost layer (prefactor).
46
42
  hamiltonian: The Hamiltonian terms for the QAOA model.
@@ -62,7 +58,6 @@ def qaoa_layer(
62
58
  Quantum Approximate Optimization Algorithm (QAOA). The cost layer encodes the problem's objective,
63
59
  while the mixer layer introduces quantum superposition and drives the search across the solution space.
64
60
 
65
- For more details mon the QAOA problem formulation, please see the following [tutorial](https://docs.classiq.io/latest/reference-manual/built-in-algorithms/combinatorial-optimization/)
66
61
  Args:
67
62
  g: The rotation parameter for the cost layer.
68
63
  b: The rotation parameter for the mixer layer.
@@ -107,9 +102,6 @@ def qaoa_penalty(
107
102
  enforce certain constraints (e.g., binary or integer variables) during the
108
103
  optimization process.
109
104
 
110
- Please refer to the [Optimization Problem tutorial](https://docs.classiq.io/latest/reference-manual/built-in-algorithms/combinatorial-optimization/problem-formulation/) for details.
111
-
112
-
113
105
  Args:
114
106
  num_qubits: The number of qubits in the quantum circuit.
115
107
  params_list The list of QAOA parameters.
@@ -46,9 +46,6 @@ def qft(target: QArray[QBit]) -> None:
46
46
 
47
47
  Args:
48
48
  target: The quantum object to be transformed
49
-
50
- Further reading in Classiq Library:
51
- Link: [qft library reference](https://github.com/Classiq/classiq-library/blob/main/functions/qmod_library_reference/classiq_open_library/qft/qft.ipynb)
52
49
  """
53
50
  repeat(
54
51
  target.len / 2, # type:ignore[arg-type]
@@ -19,9 +19,6 @@ def qpe_flexible(unitary_with_power: QCallable[CInt], phase: QNum) -> None:
19
19
  Args:
20
20
  unitary_with_power: A callable that returns the unitary operator $U^k$ given an integer $k$. This callable is used to control the application of powers of the unitary operator.
21
21
  phase: The quantum variable that represents the estimated phase (eigenvalue), assuming initialized to zero.
22
-
23
- Further reading in Classiq Library:
24
- Link: [qpe library reference](https://github.com/Classiq/classiq-library/blob/main/functions/qmod_library_reference/classiq_open_library/qpe/qpe.ipynb)
25
22
  """
26
23
  phase_array: QArray = QArray("phase_array")
27
24
  bind(phase, phase_array)
@@ -48,8 +45,5 @@ def qpe(unitary: QCallable, phase: QNum) -> None:
48
45
  Args:
49
46
  unitary: A callable representing the unitary operator $U$, whose eigenvalue is to be estimated.
50
47
  phase: The quantum variable that represents the estimated phase (eigenvalue), assuming initialized to zero.
51
-
52
- Further reading in Classiq Library:
53
- Link: [qpe library reference](https://github.com/Classiq/classiq-library/blob/main/functions/qmod_library_reference/classiq_open_library/qpe/qpe.ipynb)
54
48
  """
55
49
  qpe_flexible(unitary_with_power=lambda k: power(k, unitary), phase=phase)