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.
- classiq/__init__.py +0 -6
- classiq/_internals/client.py +11 -1
- classiq/applications/chemistry/chemistry_model_constructor.py +18 -16
- classiq/applications/combinatorial_helpers/optimization_model.py +9 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +6 -1
- classiq/applications/finance/__init__.py +0 -3
- classiq/applications/qsvm/__init__.py +0 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +22 -0
- classiq/interface/backend/quantum_backend_providers.py +2 -0
- classiq/interface/generator/expressions/expression_types.py +4 -1
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +135 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +1 -0
- classiq/interface/generator/generated_circuit_data.py +13 -0
- classiq/interface/generator/hardware/hardware_data.py +3 -1
- classiq/interface/generator/transpiler_basis_gates.py +3 -1
- classiq/interface/hardware.py +1 -0
- classiq/interface/model/handle_binding.py +21 -0
- classiq/interface/server/routes.py +0 -2
- classiq/model_expansions/atomic_expression_functions_defs.py +35 -13
- classiq/model_expansions/closure.py +0 -9
- classiq/model_expansions/evaluators/parameter_types.py +6 -10
- classiq/model_expansions/interpreters/base_interpreter.py +4 -4
- classiq/model_expansions/interpreters/generative_interpreter.py +33 -5
- classiq/model_expansions/quantum_operations/__init__.py +0 -2
- classiq/model_expansions/quantum_operations/block_evaluator.py +16 -2
- classiq/model_expansions/quantum_operations/call_emitter.py +4 -1
- classiq/model_expansions/quantum_operations/emitter.py +26 -9
- classiq/model_expansions/quantum_operations/handle_evaluator.py +1 -1
- classiq/model_expansions/quantum_operations/quantum_function_call.py +49 -0
- classiq/model_expansions/quantum_operations/repeat_block_evaluator.py +34 -0
- classiq/model_expansions/scope.py +34 -14
- classiq/model_expansions/scope_initialization.py +8 -4
- classiq/model_expansions/transformers/model_renamer.py +69 -63
- classiq/model_expansions/utils/sympy_utils.py +24 -0
- classiq/model_expansions/visitors/variable_references.py +1 -0
- classiq/qmod/builtins/functions/__init__.py +8 -0
- classiq/qmod/builtins/functions/allocation.py +36 -0
- classiq/qmod/builtins/functions/arithmetic.py +10 -5
- classiq/qmod/builtins/functions/mid_circuit_measurement.py +3 -0
- classiq/qmod/builtins/operations.py +2 -2
- classiq/qmod/model_state_container.py +9 -0
- classiq/qmod/symbolic.py +16 -3
- {classiq-0.71.0.dist-info → classiq-0.72.0.dist-info}/METADATA +1 -1
- {classiq-0.71.0.dist-info → classiq-0.72.0.dist-info}/RECORD +46 -51
- classiq/applications/finance/finance_model_constructor.py +0 -137
- classiq/applications/grover/__init__.py +0 -9
- classiq/applications/grover/grover_model_constructor.py +0 -167
- classiq/applications/libraries/__init__.py +0 -0
- classiq/applications/libraries/qmci_library.py +0 -22
- classiq/applications/qsvm/qsvm_model_constructor.py +0 -131
- classiq/model_expansions/quantum_operations/classicalif.py +0 -57
- classiq/model_expansions/quantum_operations/repeat.py +0 -62
- {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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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:
|
28
|
-
right:
|
27
|
+
left: QNum,
|
28
|
+
right: QNum,
|
29
29
|
result: Output[
|
30
|
-
|
31
|
-
|
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
|
|
@@ -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_, "
|
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("
|
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:
|
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__ = [
|