classiq 0.71.0__py3-none-any.whl → 0.72.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 (54) hide show
  1. classiq/__init__.py +0 -6
  2. classiq/_internals/client.py +11 -1
  3. classiq/applications/chemistry/chemistry_model_constructor.py +18 -16
  4. classiq/applications/combinatorial_helpers/optimization_model.py +9 -2
  5. classiq/applications/combinatorial_helpers/pyomo_utils.py +6 -1
  6. classiq/applications/finance/__init__.py +0 -3
  7. classiq/applications/qsvm/__init__.py +0 -2
  8. classiq/interface/_version.py +1 -1
  9. classiq/interface/backend/backend_preferences.py +22 -0
  10. classiq/interface/backend/quantum_backend_providers.py +2 -0
  11. classiq/interface/generator/expressions/expression_types.py +4 -1
  12. classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +135 -0
  13. classiq/interface/generator/functions/builtins/internal_operators.py +1 -0
  14. classiq/interface/generator/generated_circuit_data.py +13 -0
  15. classiq/interface/generator/hardware/hardware_data.py +3 -1
  16. classiq/interface/generator/transpiler_basis_gates.py +3 -1
  17. classiq/interface/hardware.py +1 -0
  18. classiq/interface/model/handle_binding.py +21 -0
  19. classiq/interface/server/routes.py +0 -2
  20. classiq/model_expansions/atomic_expression_functions_defs.py +35 -13
  21. classiq/model_expansions/closure.py +0 -9
  22. classiq/model_expansions/evaluators/parameter_types.py +6 -10
  23. classiq/model_expansions/interpreters/base_interpreter.py +4 -4
  24. classiq/model_expansions/interpreters/generative_interpreter.py +33 -5
  25. classiq/model_expansions/quantum_operations/__init__.py +0 -2
  26. classiq/model_expansions/quantum_operations/block_evaluator.py +16 -2
  27. classiq/model_expansions/quantum_operations/call_emitter.py +4 -1
  28. classiq/model_expansions/quantum_operations/emitter.py +26 -9
  29. classiq/model_expansions/quantum_operations/handle_evaluator.py +1 -1
  30. classiq/model_expansions/quantum_operations/quantum_function_call.py +49 -0
  31. classiq/model_expansions/quantum_operations/repeat_block_evaluator.py +34 -0
  32. classiq/model_expansions/scope.py +34 -14
  33. classiq/model_expansions/scope_initialization.py +8 -4
  34. classiq/model_expansions/transformers/model_renamer.py +69 -63
  35. classiq/model_expansions/utils/sympy_utils.py +24 -0
  36. classiq/model_expansions/visitors/variable_references.py +1 -0
  37. classiq/qmod/builtins/functions/__init__.py +8 -0
  38. classiq/qmod/builtins/functions/allocation.py +36 -0
  39. classiq/qmod/builtins/functions/arithmetic.py +10 -5
  40. classiq/qmod/builtins/functions/mid_circuit_measurement.py +3 -0
  41. classiq/qmod/builtins/operations.py +2 -2
  42. classiq/qmod/model_state_container.py +9 -0
  43. classiq/qmod/symbolic.py +16 -3
  44. {classiq-0.71.0.dist-info → classiq-0.72.0.dist-info}/METADATA +1 -1
  45. {classiq-0.71.0.dist-info → classiq-0.72.0.dist-info}/RECORD +46 -51
  46. classiq/applications/finance/finance_model_constructor.py +0 -137
  47. classiq/applications/grover/__init__.py +0 -9
  48. classiq/applications/grover/grover_model_constructor.py +0 -167
  49. classiq/applications/libraries/__init__.py +0 -0
  50. classiq/applications/libraries/qmci_library.py +0 -22
  51. classiq/applications/qsvm/qsvm_model_constructor.py +0 -131
  52. classiq/model_expansions/quantum_operations/classicalif.py +0 -57
  53. classiq/model_expansions/quantum_operations/repeat.py +0 -62
  54. {classiq-0.71.0.dist-info → classiq-0.72.0.dist-info}/WHEEL +0 -0
@@ -36,72 +36,78 @@ class HandleRenaming:
36
36
  SymbolRenaming = Mapping[HandleBinding, Sequence[HandleRenaming]]
37
37
 
38
38
 
39
- class ModelRenamer:
40
- def rewrite(self, subject: AST_NODE, symbol_mapping: SymbolRenaming) -> AST_NODE:
41
- if len(symbol_mapping) == 0:
42
- return subject
43
- handle_replacements = {
44
- part.source_handle: part.target_var_handle
45
- for parts in symbol_mapping.values()
46
- for part in parts
47
- }
39
+ def _rewrite_expression(
40
+ symbol_mapping: SymbolRenaming, expression: Expression
41
+ ) -> Expression:
42
+ vrc = VarRefCollector(
43
+ ignore_duplicated_handles=True, ignore_sympy_symbols=True, unevaluated=True
44
+ )
45
+ vrc.visit(ast.parse(expression.expr))
46
+
47
+ handle_names = {
48
+ part.source_handle: part.target_var_handle
49
+ for parts in symbol_mapping.values()
50
+ for part in parts
51
+ }
52
+ new_expr_str = expression.expr
53
+ for handle in vrc.var_handles:
54
+ new_handle = handle.collapse()
55
+ for handle_to_replace, replacement in handle_names.items():
56
+ new_handle = new_handle.replace_prefix(handle_to_replace, replacement)
57
+ new_expr_str = _replace_full_word(str(handle), str(new_handle), new_expr_str)
58
+ if handle.qmod_expr != str(handle):
59
+ new_expr_str = _replace_full_word(
60
+ str(handle.qmod_expr), str(new_handle.qmod_expr), new_expr_str
61
+ )
62
+
63
+ new_expr = Expression(expr=new_expr_str)
64
+ new_expr._evaluated_expr = expression._evaluated_expr
65
+ return new_expr
48
66
 
49
- class ReplaceSplitVars(ModelTransformer):
50
- @staticmethod
51
- def visit_HandleBinding(handle: HandleBinding) -> HandleBinding:
52
- handle = handle.collapse()
53
- for handle_to_replace, replacement in handle_replacements.items():
54
- handle = handle.replace_prefix(handle_to_replace, replacement)
55
- return handle
56
-
57
- @staticmethod
58
- def visit_Expression(expr: Expression) -> Expression:
59
- return self._rewrite_expression(symbol_mapping, expr)
60
-
61
- def visit_QuantumExpressionOperation(
62
- self, op: QuantumExpressionOperation
63
- ) -> QuantumExpressionOperation:
64
- op = cast(QuantumExpressionOperation, self.generic_visit(op))
65
- previous_var_handles = list(op._var_handles)
66
- op._var_handles = self.visit(op._var_handles)
67
- op._var_types = {
68
- new_handle.name: op._var_types.get(
69
- new_handle.name, op._var_types[previous_handle.name]
70
- )
71
- for previous_handle, new_handle in zip(
72
- previous_var_handles, op._var_handles
73
- )
74
- }
75
- return op
76
-
77
- return ReplaceSplitVars().visit(subject)
78
-
79
- def _rewrite_expression(
80
- self,
81
- symbol_mapping: SymbolRenaming,
82
- expression: Expression,
83
- ) -> Expression:
84
- vrc = VarRefCollector(ignore_duplicated_handles=True, ignore_sympy_symbols=True)
85
- vrc.visit(ast.parse(expression.expr))
86
-
87
- handle_names = {
67
+
68
+ class _ReplaceSplitVarsHandles(ModelTransformer):
69
+ def __init__(self, symbol_mapping: SymbolRenaming) -> None:
70
+ self._handle_replacements = {
88
71
  part.source_handle: part.target_var_handle
89
72
  for parts in symbol_mapping.values()
90
73
  for part in parts
91
74
  }
92
- new_expr_str = expression.expr
93
- for handle in vrc.var_handles:
94
- new_handle = handle.collapse()
95
- for handle_to_replace, replacement in handle_names.items():
96
- new_handle = new_handle.replace_prefix(handle_to_replace, replacement)
97
- new_expr_str = _replace_full_word(
98
- str(handle), str(new_handle), new_expr_str
75
+
76
+ def visit_HandleBinding(self, handle: HandleBinding) -> HandleBinding:
77
+ handle = handle.collapse()
78
+ for handle_to_replace, replacement in self._handle_replacements.items():
79
+ handle = handle.replace_prefix(handle_to_replace, replacement)
80
+ return handle
81
+
82
+
83
+ class _ReplaceSplitVarsExpressions(ModelTransformer):
84
+ def __init__(self, symbol_mapping: SymbolRenaming) -> None:
85
+ self._symbol_mapping = symbol_mapping
86
+
87
+ def visit_Expression(self, expr: Expression) -> Expression:
88
+ return _rewrite_expression(self._symbol_mapping, expr)
89
+
90
+ def visit_QuantumExpressionOperation(
91
+ self, op: QuantumExpressionOperation
92
+ ) -> QuantumExpressionOperation:
93
+ op = cast(QuantumExpressionOperation, self.generic_visit(op))
94
+ previous_var_handles = list(op._var_handles)
95
+ op._var_handles = self.visit(op._var_handles)
96
+ op._var_types = {
97
+ new_handle.name: op._var_types.get(
98
+ new_handle.name, op._var_types[previous_handle.name]
99
99
  )
100
- if handle.qmod_expr != str(handle):
101
- new_expr_str = _replace_full_word(
102
- str(handle.qmod_expr), str(new_handle.qmod_expr), new_expr_str
103
- )
104
-
105
- new_expr = Expression(expr=new_expr_str)
106
- new_expr._evaluated_expr = expression._evaluated_expr
107
- return new_expr
100
+ for previous_handle, new_handle in zip(
101
+ previous_var_handles, op._var_handles
102
+ )
103
+ }
104
+ return op
105
+
106
+
107
+ class ModelRenamer:
108
+ def rewrite(self, subject: AST_NODE, symbol_mapping: SymbolRenaming) -> AST_NODE:
109
+ if len(symbol_mapping) == 0:
110
+ return subject
111
+ subject = _ReplaceSplitVarsHandles(symbol_mapping).visit(subject)
112
+ subject = _ReplaceSplitVarsExpressions(symbol_mapping).visit(subject)
113
+ return subject
@@ -0,0 +1,24 @@
1
+ from typing import Any
2
+
3
+ from sympy import Number
4
+
5
+
6
+ def unwrap_sympy_numeric(n: Any) -> Any:
7
+ if not isinstance(n, Number) or not n.is_constant():
8
+ return n
9
+ if n.is_Integer:
10
+ return int(n)
11
+ return float(n)
12
+
13
+
14
+ def is_constant_subscript(index: Any) -> bool:
15
+ if not isinstance(index, slice):
16
+ return isinstance(unwrap_sympy_numeric(index), int)
17
+ start = unwrap_sympy_numeric(index.start)
18
+ stop = unwrap_sympy_numeric(index.stop)
19
+ step = unwrap_sympy_numeric(index.step)
20
+ return (
21
+ (start is None or isinstance(start, int))
22
+ and (stop is None or isinstance(stop, int))
23
+ and (step is None or isinstance(step, int))
24
+ )
@@ -58,6 +58,7 @@ class VarRefCollector(ast.NodeVisitor):
58
58
  def visit_Subscript(
59
59
  self, node: ast.Subscript
60
60
  ) -> Union[SubscriptHandleBinding, SlicedHandleBinding, None]:
61
+ self.visit(node.slice)
61
62
  with self.set_nested():
62
63
  base_handle = self.visit(node.value)
63
64
  if base_handle is None:
@@ -50,7 +50,9 @@ CORE_LIB_DECLS = [
50
50
  SWAP,
51
51
  IDENTITY,
52
52
  prepare_state,
53
+ prepare_state_approx,
53
54
  prepare_amplitudes,
55
+ prepare_amplitudes_approx,
54
56
  unitary,
55
57
  add,
56
58
  modular_add,
@@ -62,7 +64,9 @@ CORE_LIB_DECLS = [
62
64
  free,
63
65
  randomized_benchmarking,
64
66
  inplace_prepare_state,
67
+ inplace_prepare_state_approx,
65
68
  inplace_prepare_amplitudes,
69
+ inplace_prepare_amplitudes_approx,
66
70
  single_pauli_exponent,
67
71
  commuting_paulis_exponent,
68
72
  suzuki_trotter,
@@ -114,7 +118,9 @@ __all__ = [ # noqa: RUF022
114
118
  "free",
115
119
  "gaussian_finance",
116
120
  "inplace_prepare_amplitudes",
121
+ "inplace_prepare_amplitudes_approx",
117
122
  "inplace_prepare_state",
123
+ "inplace_prepare_state_approx",
118
124
  "integer_xor",
119
125
  "log_normal_finance",
120
126
  "modular_add",
@@ -125,7 +131,9 @@ __all__ = [ # noqa: RUF022
125
131
  "pauli_feature_map",
126
132
  "permute",
127
133
  "prepare_amplitudes",
134
+ "prepare_amplitudes_approx",
128
135
  "prepare_state",
136
+ "prepare_state_approx",
129
137
  "qdrift",
130
138
  "randomized_benchmarking",
131
139
  "real_xor_constant",
@@ -123,3 +123,39 @@ def inplace_prepare_amplitudes(
123
123
 
124
124
  """
125
125
  pass
126
+
127
+
128
+ @qfunc(external=True)
129
+ def inplace_prepare_amplitudes_approx(
130
+ amplitudes: CArray[CReal],
131
+ bound: CReal,
132
+ target: QArray[QBit, Literal["log(get_field(amplitudes, 'len'), 2)"]],
133
+ ) -> None:
134
+ pass
135
+
136
+
137
+ @qfunc(external=True)
138
+ def prepare_amplitudes_approx(
139
+ amplitudes: CArray[CReal],
140
+ bound: CReal,
141
+ out: Output[QArray[QBit, Literal["log(get_field(amplitudes, 'len'), 2)"]]],
142
+ ) -> None:
143
+ pass
144
+
145
+
146
+ @qfunc(external=True)
147
+ def inplace_prepare_state_approx(
148
+ probabilities: CArray[CReal],
149
+ bound: CReal,
150
+ target: QArray[QBit, Literal["log(get_field(probabilities, 'len'), 2)"]],
151
+ ) -> None:
152
+ pass
153
+
154
+
155
+ @qfunc(external=True)
156
+ def prepare_state_approx(
157
+ probabilities: CArray[CReal],
158
+ bound: CReal,
159
+ out: Output[QArray[QBit, Literal["log(get_field(probabilities, 'len'), 2)"]]],
160
+ ) -> None:
161
+ pass
@@ -1,7 +1,7 @@
1
1
  from typing import Literal
2
2
 
3
3
  from classiq.qmod.qfunc import qfunc
4
- from classiq.qmod.qmod_parameter import CArray, CReal
4
+ from classiq.qmod.qmod_parameter import CArray, CBool, CReal
5
5
  from classiq.qmod.qmod_variable import Output, QArray, QBit, QNum
6
6
 
7
7
 
@@ -24,13 +24,18 @@ def unitary(
24
24
 
25
25
  @qfunc(external=True)
26
26
  def add(
27
- left: QArray[QBit],
28
- right: QArray[QBit],
27
+ left: QNum,
28
+ right: QNum,
29
29
  result: Output[
30
- QArray[
31
- QBit, Literal["Max(get_field(left, 'len'), get_field(right, 'len')) + 1"]
30
+ QNum[
31
+ Literal["result_size"],
32
+ Literal["result_is_signed"],
33
+ Literal["result_fraction_places"],
32
34
  ]
33
35
  ],
36
+ result_size: CReal,
37
+ result_is_signed: CBool,
38
+ result_fraction_places: CReal,
34
39
  ) -> None:
35
40
  pass
36
41
 
@@ -11,5 +11,8 @@ def RESET(target: QBit) -> None:
11
11
 
12
12
  Args:
13
13
  target: the qubit to reset
14
+
15
+ Notes:
16
+ We approximate the depth of a single RESET gate to 1000 X gates.
14
17
  """
15
18
  pass
@@ -142,13 +142,13 @@ def if_(
142
142
  if_stmt = ClassicalIf(
143
143
  condition=Expression(expr=str(condition)),
144
144
  then=_operand_to_body(then, "then"),
145
- else_=_operand_to_body(else_, "else") if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
145
+ else_=_operand_to_body(else_, "else_") if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
146
146
  source_ref=source_ref,
147
147
  )
148
148
  if is_generative_mode():
149
149
  if_stmt.set_generative_block("then", then)
150
150
  if callable(else_):
151
- if_stmt.set_generative_block("else", else_)
151
+ if_stmt.set_generative_block("else_", else_)
152
152
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(if_stmt)
153
153
 
154
154
 
@@ -1,3 +1,4 @@
1
+ from collections import defaultdict
1
2
  from typing import TYPE_CHECKING
2
3
 
3
4
  from classiq.interface.generator.constant import Constant
@@ -25,3 +26,11 @@ class ModelStateContainer:
25
26
 
26
27
 
27
28
  QMODULE = ModelStateContainer()
29
+ QMODULE.enum_decls = {}
30
+ QMODULE.type_decls = {}
31
+ QMODULE.qstruct_decls = {}
32
+ QMODULE.native_defs = {}
33
+ QMODULE.constants = {}
34
+ QMODULE.functions_compilation_metadata = {}
35
+ QMODULE.generative_functions = {}
36
+ QMODULE.function_dependencies = defaultdict(list)
classiq/qmod/symbolic.py CHANGED
@@ -20,7 +20,6 @@ from classiq.qmod.qmod_parameter import (
20
20
  CReal,
21
21
  create_param,
22
22
  )
23
- from classiq.qmod.qmod_variable import QNum
24
23
  from classiq.qmod.symbolic_expr import SymbolicExpr
25
24
  from classiq.qmod.symbolic_type import SymbolicTypes
26
25
 
@@ -296,11 +295,25 @@ def sum(arr: SymbolicTypes) -> CParamScalar:
296
295
  return symbolic_function(arr)
297
296
 
298
297
 
298
+ def _subscript_to_str(index: Any) -> str:
299
+ if not isinstance(index, slice):
300
+ return str(index)
301
+ expr = ""
302
+ if index.start is not None:
303
+ expr += str(index.start)
304
+ expr += ":"
305
+ if index.stop is not None:
306
+ expr += str(index.stop)
307
+ if index.step is not None:
308
+ expr += f":{index.step}"
309
+ return expr
310
+
311
+
299
312
  def subscript(
300
313
  amplitudes: Union[Sequence[Union[float, CReal, CParamScalar]], CArray[CReal]],
301
- index: QNum,
314
+ index: Any,
302
315
  ) -> CParamScalar:
303
- return CParamScalar(expr=f"{amplitudes}[{index}]")
316
+ return CParamScalar(expr=f"{amplitudes}[{_subscript_to_str(index)}]")
304
317
 
305
318
 
306
319
  __all__ = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: classiq
3
- Version: 0.71.0
3
+ Version: 0.72.0
4
4
  Summary: Classiq's Python SDK for quantum computing
5
5
  License: Proprietary
6
6
  Keywords: quantum computing,quantum circuits,quantum algorithms,QAD,QDL