classiq 0.70.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/debug_info/debug_info.py +4 -0
- classiq/interface/generator/expressions/expression_constants.py +0 -3
- classiq/interface/generator/expressions/expression_types.py +8 -3
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +135 -0
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -0
- classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +5 -1
- classiq/interface/generator/expressions/proxies/classical/utils.py +34 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +1 -0
- classiq/interface/generator/functions/classical_type.py +1 -1
- classiq/interface/generator/functions/type_name.py +16 -0
- classiq/interface/generator/functions/type_qualifier.py +7 -0
- classiq/interface/generator/generated_circuit_data.py +14 -1
- classiq/interface/generator/hardware/hardware_data.py +3 -1
- classiq/interface/generator/quantum_function_call.py +8 -1
- classiq/interface/generator/synthesis_execution_parameter.py +1 -0
- classiq/interface/generator/transpiler_basis_gates.py +3 -1
- classiq/interface/generator/types/compilation_metadata.py +1 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/ide/visual_model.py +1 -0
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/allocate.py +7 -0
- classiq/interface/model/block.py +12 -0
- classiq/interface/model/classical_if.py +4 -0
- classiq/interface/model/handle_binding.py +21 -0
- classiq/interface/model/inplace_binary_operation.py +4 -0
- classiq/interface/model/model.py +3 -1
- classiq/interface/model/phase_operation.py +4 -0
- classiq/interface/model/port_declaration.py +3 -0
- classiq/interface/model/power.py +4 -0
- classiq/interface/model/quantum_expressions/quantum_expression.py +4 -0
- classiq/interface/model/quantum_function_call.py +4 -0
- classiq/interface/model/quantum_function_declaration.py +1 -1
- classiq/interface/model/quantum_statement.py +5 -0
- classiq/interface/model/quantum_type.py +22 -0
- classiq/interface/model/repeat.py +4 -0
- classiq/interface/model/statement_block.py +3 -0
- classiq/interface/model/variable_declaration_statement.py +5 -0
- classiq/interface/server/routes.py +0 -2
- classiq/model_expansions/atomic_expression_functions_defs.py +35 -13
- classiq/model_expansions/capturing/captured_vars.py +156 -34
- classiq/model_expansions/closure.py +0 -9
- classiq/model_expansions/evaluators/classical_type_inference.py +70 -0
- classiq/model_expansions/evaluators/parameter_types.py +20 -10
- classiq/model_expansions/expression_evaluator.py +0 -11
- classiq/model_expansions/function_builder.py +2 -8
- classiq/model_expansions/generative_functions.py +7 -30
- classiq/model_expansions/interpreters/base_interpreter.py +7 -8
- 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 +49 -6
- classiq/model_expansions/quantum_operations/emitter.py +64 -6
- classiq/model_expansions/quantum_operations/expression_evaluator.py +4 -0
- 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 +33 -21
- classiq/model_expansions/scope_initialization.py +28 -32
- 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/__init__.py +3 -1
- 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/declaration_inferrer.py +52 -24
- classiq/qmod/model_state_container.py +9 -0
- classiq/qmod/native/pretty_printer.py +25 -3
- classiq/qmod/pretty_print/pretty_printer.py +31 -14
- classiq/qmod/python_classical_type.py +12 -1
- classiq/qmod/qfunc.py +33 -8
- classiq/qmod/qmod_variable.py +188 -147
- classiq/qmod/quantum_function.py +3 -4
- classiq/qmod/semantics/validation/type_hints.py +19 -10
- classiq/qmod/symbolic.py +16 -3
- {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/METADATA +1 -1
- {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/RECORD +90 -91
- 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.70.0.dist-info → classiq-0.72.0.dist-info}/WHEEL +0 -0
@@ -1,137 +0,0 @@
|
|
1
|
-
import warnings
|
2
|
-
from math import floor, log
|
3
|
-
from typing import Union
|
4
|
-
|
5
|
-
from classiq.interface.exceptions import ClassiqError
|
6
|
-
from classiq.interface.finance.function_input import FinanceFunctionInput
|
7
|
-
from classiq.interface.finance.gaussian_model_input import GaussianModelInput
|
8
|
-
from classiq.interface.finance.log_normal_model_input import LogNormalModelInput
|
9
|
-
from classiq.interface.generator.expressions.expression import Expression
|
10
|
-
from classiq.interface.generator.functions.port_declaration import (
|
11
|
-
PortDeclarationDirection,
|
12
|
-
)
|
13
|
-
from classiq.interface.model.allocate import Allocate
|
14
|
-
from classiq.interface.model.handle_binding import HandleBinding
|
15
|
-
from classiq.interface.model.model import Model, SerializedModel
|
16
|
-
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
17
|
-
from classiq.interface.model.port_declaration import PortDeclaration
|
18
|
-
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
19
|
-
from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
|
20
|
-
from classiq.interface.model.quantum_type import QuantumNumeric
|
21
|
-
from classiq.interface.model.variable_declaration_statement import (
|
22
|
-
VariableDeclarationStatement,
|
23
|
-
)
|
24
|
-
|
25
|
-
from classiq.applications.libraries.qmci_library import QMCI_LIBRARY
|
26
|
-
from classiq.qmod.utilities import qmod_val_to_expr_str
|
27
|
-
|
28
|
-
_OUTPUT_VARIABLE_NAME = "payoff_estimation"
|
29
|
-
|
30
|
-
|
31
|
-
def construct_finance_model(
|
32
|
-
finance_model_input: Union[LogNormalModelInput, GaussianModelInput],
|
33
|
-
finance_function_input: FinanceFunctionInput,
|
34
|
-
phase_port_size: int,
|
35
|
-
) -> SerializedModel:
|
36
|
-
warnings.warn(
|
37
|
-
"Function 'construct_finance_model' has been deprecated and will no longer"
|
38
|
-
"be supported starting on 03/02/2025 the earliest\nHint: It is now possible to "
|
39
|
-
"implement Option Pricing in pure Qmod. For example, see the Option Pricing notebook on the "
|
40
|
-
"Classiq library at https://github.com/Classiq/classiq-library/blob/main/applications/finance/option_pricing/option_pricing.ipynb",
|
41
|
-
category=DeprecationWarning,
|
42
|
-
stacklevel=2,
|
43
|
-
)
|
44
|
-
if isinstance(finance_model_input, LogNormalModelInput):
|
45
|
-
finance_model = f"struct_literal(LogNormalModel, num_qubits={finance_model_input.num_qubits}, mu={finance_model_input.mu}, sigma={finance_model_input.sigma})"
|
46
|
-
finance_function = "log_normal_finance"
|
47
|
-
post_process_function = "log_normal_finance_post_process"
|
48
|
-
total_num_qubits = finance_model_input.num_qubits
|
49
|
-
elif isinstance(finance_model_input, GaussianModelInput):
|
50
|
-
finance_model = f"struct_literal(GaussianModel, num_qubits={finance_model_input.num_qubits}, normal_max_value={finance_model_input.normal_max_value}, default_probabilities={finance_model_input.default_probabilities}, rhos={finance_model_input.rhos}, loss={finance_model_input.loss}, min_loss={finance_model_input.min_loss})"
|
51
|
-
finance_function = "gaussian_finance"
|
52
|
-
post_process_function = "gaussian_finance_post_process"
|
53
|
-
total_num_qubits = (
|
54
|
-
finance_model_input.num_qubits
|
55
|
-
+ len(finance_model_input.rhos)
|
56
|
-
+ floor(log(sum(finance_model_input.loss), 2))
|
57
|
-
+ 1
|
58
|
-
)
|
59
|
-
else:
|
60
|
-
raise ClassiqError(f"Invalid model input: {finance_model_input}")
|
61
|
-
|
62
|
-
polynomial_degree = 0
|
63
|
-
if finance_function_input.polynomial_degree is not None:
|
64
|
-
polynomial_degree = finance_function_input.polynomial_degree
|
65
|
-
|
66
|
-
tail_probability = 0.0
|
67
|
-
if finance_function_input.tail_probability is not None:
|
68
|
-
tail_probability = finance_function_input.tail_probability
|
69
|
-
|
70
|
-
finance_function_object = f"struct_literal(FinanceFunction, f={qmod_val_to_expr_str(finance_function_input.f)}, threshold={finance_function_input.condition.threshold}, larger={finance_function_input.condition.larger}, polynomial_degree={polynomial_degree}, use_chebyshev_polynomial_approximation={finance_function_input.use_chebyshev_polynomial_approximation}, tail_probability={tail_probability})"
|
71
|
-
num_unitary_qubits = total_num_qubits + 1
|
72
|
-
|
73
|
-
model = Model(
|
74
|
-
functions=[
|
75
|
-
*QMCI_LIBRARY,
|
76
|
-
NativeFunctionDefinition(
|
77
|
-
name="main",
|
78
|
-
positional_arg_declarations=[
|
79
|
-
PortDeclaration(
|
80
|
-
name="phase_port",
|
81
|
-
quantum_type=QuantumNumeric(
|
82
|
-
size=Expression(expr=f"{phase_port_size}"),
|
83
|
-
is_signed=Expression(expr="False"),
|
84
|
-
fraction_digits=Expression(expr=f"{phase_port_size}"),
|
85
|
-
),
|
86
|
-
direction=PortDeclarationDirection.Output,
|
87
|
-
),
|
88
|
-
],
|
89
|
-
body=[
|
90
|
-
VariableDeclarationStatement(name="unitary_port"),
|
91
|
-
Allocate(
|
92
|
-
size=Expression(expr=f"{num_unitary_qubits}"),
|
93
|
-
target=HandleBinding(name="unitary_port"),
|
94
|
-
),
|
95
|
-
Allocate(
|
96
|
-
size=Expression(expr=f"{phase_port_size}"),
|
97
|
-
target=HandleBinding(name="phase_port"),
|
98
|
-
),
|
99
|
-
QuantumFunctionCall(
|
100
|
-
function="qmci",
|
101
|
-
positional_args=[
|
102
|
-
QuantumLambdaFunction(
|
103
|
-
pos_rename_params=["state", "ind"],
|
104
|
-
body=[
|
105
|
-
QuantumFunctionCall(
|
106
|
-
function=finance_function,
|
107
|
-
positional_args=[
|
108
|
-
Expression(expr=finance_model),
|
109
|
-
Expression(expr=finance_function_object),
|
110
|
-
HandleBinding(name="state"),
|
111
|
-
HandleBinding(name="ind"),
|
112
|
-
],
|
113
|
-
),
|
114
|
-
],
|
115
|
-
),
|
116
|
-
HandleBinding(name="phase_port"),
|
117
|
-
HandleBinding(name="unitary_port"),
|
118
|
-
],
|
119
|
-
),
|
120
|
-
],
|
121
|
-
),
|
122
|
-
],
|
123
|
-
classical_execution_code=f"""
|
124
|
-
phase_port_size = {phase_port_size}
|
125
|
-
counts = sample()
|
126
|
-
save({{"counts": counts}})
|
127
|
-
probability_estimation = qae_with_qpe_result_post_processing(
|
128
|
-
estimation_register_size=phase_port_size,
|
129
|
-
estimation_method=1,
|
130
|
-
result=counts
|
131
|
-
)
|
132
|
-
save({{"probability_estimation": probability_estimation}})
|
133
|
-
{_OUTPUT_VARIABLE_NAME} = {post_process_function}({finance_model}, {finance_function_object}, probability_estimation)
|
134
|
-
save({{"{_OUTPUT_VARIABLE_NAME}": {_OUTPUT_VARIABLE_NAME}}})
|
135
|
-
""".strip(),
|
136
|
-
)
|
137
|
-
return model.get_model()
|
@@ -1,167 +0,0 @@
|
|
1
|
-
import warnings
|
2
|
-
|
3
|
-
from classiq.interface.generator.expressions.expression import Expression
|
4
|
-
from classiq.interface.generator.functions.port_declaration import (
|
5
|
-
PortDeclarationDirection,
|
6
|
-
)
|
7
|
-
from classiq.interface.model.allocate import Allocate
|
8
|
-
from classiq.interface.model.bind_operation import BindOperation
|
9
|
-
from classiq.interface.model.handle_binding import HandleBinding, SlicedHandleBinding
|
10
|
-
from classiq.interface.model.model import Model, SerializedModel
|
11
|
-
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
12
|
-
from classiq.interface.model.port_declaration import PortDeclaration
|
13
|
-
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
14
|
-
ArithmeticOperation,
|
15
|
-
ArithmeticOperationKind,
|
16
|
-
)
|
17
|
-
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
18
|
-
from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
|
19
|
-
from classiq.interface.model.quantum_type import QuantumBitvector, QuantumNumeric
|
20
|
-
from classiq.interface.model.variable_declaration_statement import (
|
21
|
-
VariableDeclarationStatement,
|
22
|
-
)
|
23
|
-
|
24
|
-
from classiq import RegisterUserInput
|
25
|
-
from classiq.open_library.functions.grover import grover_search, phase_oracle
|
26
|
-
|
27
|
-
_OUTPUT_VARIABLE_NAME = "result"
|
28
|
-
|
29
|
-
_PREDICATE_FUNCTION_NAME = "expr_predicate"
|
30
|
-
|
31
|
-
|
32
|
-
def _arithmetic_oracle_ios(
|
33
|
-
definitions: list[tuple[str, RegisterUserInput]], handle_name: str
|
34
|
-
) -> list[HandleBinding]:
|
35
|
-
cursor = 0
|
36
|
-
ios: list[HandleBinding] = []
|
37
|
-
for _, reg in definitions:
|
38
|
-
ios.append(
|
39
|
-
SlicedHandleBinding(
|
40
|
-
base_handle=HandleBinding(name=handle_name),
|
41
|
-
start=Expression(expr=f"{cursor}"),
|
42
|
-
end=Expression(expr=f"{cursor + reg.size}"),
|
43
|
-
)
|
44
|
-
)
|
45
|
-
cursor += reg.size
|
46
|
-
return ios
|
47
|
-
|
48
|
-
|
49
|
-
def _construct_arithmetic_oracle(
|
50
|
-
predicate_function: str,
|
51
|
-
definitions: list[tuple[str, RegisterUserInput]],
|
52
|
-
) -> QuantumFunctionCall:
|
53
|
-
predicate_var_binding = _arithmetic_oracle_ios(definitions, "state")
|
54
|
-
predicate_var_binding.append(HandleBinding(name="oracle"))
|
55
|
-
return QuantumFunctionCall(
|
56
|
-
function="phase_oracle",
|
57
|
-
positional_args=[
|
58
|
-
QuantumLambdaFunction(
|
59
|
-
pos_rename_params=["state", "oracle"],
|
60
|
-
body=[
|
61
|
-
QuantumFunctionCall(
|
62
|
-
function=predicate_function,
|
63
|
-
positional_args=predicate_var_binding,
|
64
|
-
),
|
65
|
-
],
|
66
|
-
),
|
67
|
-
HandleBinding(name="packed_vars"),
|
68
|
-
],
|
69
|
-
)
|
70
|
-
|
71
|
-
|
72
|
-
def grover_main_port_declarations(
|
73
|
-
definitions: list[tuple[str, RegisterUserInput]],
|
74
|
-
direction: PortDeclarationDirection,
|
75
|
-
) -> list[PortDeclaration]:
|
76
|
-
return [
|
77
|
-
PortDeclaration(
|
78
|
-
name=name,
|
79
|
-
quantum_type=QuantumNumeric(
|
80
|
-
size=Expression(expr=f"{reg.size}"),
|
81
|
-
is_signed=Expression(expr=f"{reg.is_signed}"),
|
82
|
-
fraction_digits=Expression(expr=f"{reg.fraction_places}"),
|
83
|
-
),
|
84
|
-
direction=direction,
|
85
|
-
)
|
86
|
-
for name, reg in definitions
|
87
|
-
]
|
88
|
-
|
89
|
-
|
90
|
-
def construct_grover_model(
|
91
|
-
definitions: list[tuple[str, RegisterUserInput]],
|
92
|
-
expression: str,
|
93
|
-
num_reps: int = 1,
|
94
|
-
) -> SerializedModel:
|
95
|
-
warnings.warn(
|
96
|
-
"Function 'construct_grover_model' has been deprecated and will no longer"
|
97
|
-
"be supported starting on 03/02/2025 the earliest\nHint: It is now possible to "
|
98
|
-
"implement the Grover algorithm in pure Qmod. For example, see the Grover notebook on the "
|
99
|
-
"Classiq library at https://github.com/Classiq/classiq-library/blob/main/algorithms/grover/3_sat_grover/3_sat_grover.ipynb",
|
100
|
-
category=DeprecationWarning,
|
101
|
-
stacklevel=2,
|
102
|
-
)
|
103
|
-
predicate_port_decls = grover_main_port_declarations(
|
104
|
-
definitions, PortDeclarationDirection.Inout
|
105
|
-
)
|
106
|
-
predicate_port_decls.append(
|
107
|
-
PortDeclaration(
|
108
|
-
name="res",
|
109
|
-
quantum_type=QuantumBitvector(length=Expression(expr="1")),
|
110
|
-
direction=PortDeclarationDirection.Inout,
|
111
|
-
)
|
112
|
-
)
|
113
|
-
num_qubits = sum(reg.size for _, reg in definitions)
|
114
|
-
|
115
|
-
grover_model = Model(
|
116
|
-
functions=[
|
117
|
-
NativeFunctionDefinition(
|
118
|
-
name=_PREDICATE_FUNCTION_NAME,
|
119
|
-
positional_arg_declarations=predicate_port_decls,
|
120
|
-
body=[
|
121
|
-
ArithmeticOperation(
|
122
|
-
expression=Expression(expr=expression),
|
123
|
-
result_var=HandleBinding(name="res"),
|
124
|
-
operation_kind=ArithmeticOperationKind.InplaceXor,
|
125
|
-
),
|
126
|
-
],
|
127
|
-
),
|
128
|
-
NativeFunctionDefinition(
|
129
|
-
name="main",
|
130
|
-
positional_arg_declarations=grover_main_port_declarations(
|
131
|
-
definitions, PortDeclarationDirection.Output
|
132
|
-
),
|
133
|
-
body=[
|
134
|
-
VariableDeclarationStatement(name="packed_vars"),
|
135
|
-
Allocate(
|
136
|
-
size=Expression(expr=f"{num_qubits}"),
|
137
|
-
target=HandleBinding(name="packed_vars"),
|
138
|
-
),
|
139
|
-
QuantumFunctionCall(
|
140
|
-
function="grover_search",
|
141
|
-
positional_args=[
|
142
|
-
Expression(expr=f"{num_reps}"),
|
143
|
-
QuantumLambdaFunction(
|
144
|
-
pos_rename_params=["packed_vars"],
|
145
|
-
body=[
|
146
|
-
_construct_arithmetic_oracle(
|
147
|
-
_PREDICATE_FUNCTION_NAME,
|
148
|
-
definitions,
|
149
|
-
)
|
150
|
-
],
|
151
|
-
),
|
152
|
-
HandleBinding(name="packed_vars"),
|
153
|
-
],
|
154
|
-
),
|
155
|
-
BindOperation(
|
156
|
-
in_handles=[HandleBinding(name="packed_vars")],
|
157
|
-
out_handles=[
|
158
|
-
HandleBinding(name=name) for name, _ in definitions
|
159
|
-
],
|
160
|
-
),
|
161
|
-
],
|
162
|
-
),
|
163
|
-
*[f for f in grover_search.create_model().functions if f.name != "main"],
|
164
|
-
*[f for f in phase_oracle.create_model().functions if f.name != "main"],
|
165
|
-
],
|
166
|
-
)
|
167
|
-
return grover_model.get_model()
|
File without changes
|
@@ -1,22 +0,0 @@
|
|
1
|
-
from classiq.open_library.functions.amplitude_estimation import amplitude_estimation
|
2
|
-
from classiq.qmod.builtins.functions import Z
|
3
|
-
from classiq.qmod.qfunc import qfunc
|
4
|
-
from classiq.qmod.qmod_variable import QArray, QBit, QNum
|
5
|
-
from classiq.qmod.quantum_callable import QCallable
|
6
|
-
|
7
|
-
|
8
|
-
@qfunc
|
9
|
-
def qmci(
|
10
|
-
space_transform: QCallable[QArray[QBit], QBit],
|
11
|
-
phase: QNum,
|
12
|
-
packed_vars: QArray[QBit],
|
13
|
-
) -> None:
|
14
|
-
amplitude_estimation(
|
15
|
-
lambda reg: Z(reg[reg.len - 1]),
|
16
|
-
lambda reg: space_transform(reg[0 : reg.len - 1], reg[reg.len - 1]),
|
17
|
-
phase,
|
18
|
-
packed_vars,
|
19
|
-
)
|
20
|
-
|
21
|
-
|
22
|
-
QMCI_LIBRARY = [func for func in qmci.create_model().functions if func.name != "main"]
|
@@ -1,131 +0,0 @@
|
|
1
|
-
import warnings
|
2
|
-
from typing import Any
|
3
|
-
|
4
|
-
from classiq.interface.applications.qsvm import DataList, LabelsInt
|
5
|
-
from classiq.interface.exceptions import ClassiqValueError
|
6
|
-
from classiq.interface.generator.expressions.expression import Expression
|
7
|
-
from classiq.interface.generator.functions.port_declaration import (
|
8
|
-
PortDeclarationDirection,
|
9
|
-
)
|
10
|
-
from classiq.interface.model.allocate import Allocate
|
11
|
-
from classiq.interface.model.handle_binding import HandleBinding
|
12
|
-
from classiq.interface.model.model import Model, SerializedModel
|
13
|
-
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
14
|
-
from classiq.interface.model.port_declaration import PortDeclaration
|
15
|
-
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
16
|
-
from classiq.interface.model.quantum_statement import QuantumStatement
|
17
|
-
|
18
|
-
from classiq.qmod.builtins.enums import Pauli, QSVMFeatureMapEntanglement
|
19
|
-
from classiq.qmod.utilities import qmod_val_to_expr_str
|
20
|
-
|
21
|
-
INVALID_FEATURE_MAP_FUNC_NAME_MSG = "Invalid feature_map_function_name, it can be bloch_sphere_feature_map or pauli_feature_map"
|
22
|
-
|
23
|
-
_OUTPUT_VARIABLE_NAME = "qsvm_results"
|
24
|
-
|
25
|
-
|
26
|
-
def _bloch_sphere_feature_map_function_params(
|
27
|
-
bloch_feature_dimension: int,
|
28
|
-
) -> tuple[list[Expression], str]:
|
29
|
-
return [
|
30
|
-
Expression(expr=f"{bloch_feature_dimension}")
|
31
|
-
], f"ceiling({bloch_feature_dimension}/2)"
|
32
|
-
|
33
|
-
|
34
|
-
def _pauli_feature_map_function_params(
|
35
|
-
paulis: list[list[Pauli]],
|
36
|
-
entanglement: QSVMFeatureMapEntanglement,
|
37
|
-
alpha: int,
|
38
|
-
reps: int,
|
39
|
-
feature_dimension: int,
|
40
|
-
) -> tuple[list[Expression], str]:
|
41
|
-
paulis_str = (
|
42
|
-
"["
|
43
|
-
+ ",".join(
|
44
|
-
[
|
45
|
-
"[" + ",".join([qmod_val_to_expr_str(p) for p in p_list]) + "]"
|
46
|
-
for p_list in paulis
|
47
|
-
]
|
48
|
-
)
|
49
|
-
+ "]"
|
50
|
-
)
|
51
|
-
pauli_feature_map_params = (
|
52
|
-
f"paulis={paulis_str}, "
|
53
|
-
f"entanglement={qmod_val_to_expr_str(entanglement)}, "
|
54
|
-
f"alpha={alpha}, "
|
55
|
-
f"reps={reps}, "
|
56
|
-
f"feature_dimension={feature_dimension}"
|
57
|
-
)
|
58
|
-
return [
|
59
|
-
Expression(
|
60
|
-
expr=f"struct_literal(QSVMFeatureMapPauli, {pauli_feature_map_params})"
|
61
|
-
)
|
62
|
-
], f"{feature_dimension}"
|
63
|
-
|
64
|
-
|
65
|
-
def get_qsvm_qmain_body(
|
66
|
-
feature_map_function_name: str, **kwargs: Any
|
67
|
-
) -> list[QuantumStatement]:
|
68
|
-
if feature_map_function_name == "bloch_sphere_feature_map":
|
69
|
-
params, size_expr = _bloch_sphere_feature_map_function_params(**kwargs)
|
70
|
-
elif feature_map_function_name == "pauli_feature_map":
|
71
|
-
params, size_expr = _pauli_feature_map_function_params(**kwargs)
|
72
|
-
else:
|
73
|
-
raise ClassiqValueError(INVALID_FEATURE_MAP_FUNC_NAME_MSG)
|
74
|
-
|
75
|
-
return [
|
76
|
-
Allocate(
|
77
|
-
size=Expression(expr=size_expr),
|
78
|
-
target=HandleBinding(name="qbv"),
|
79
|
-
),
|
80
|
-
QuantumFunctionCall(
|
81
|
-
function=feature_map_function_name,
|
82
|
-
positional_args=[*params, HandleBinding(name="qbv")],
|
83
|
-
),
|
84
|
-
]
|
85
|
-
|
86
|
-
|
87
|
-
def construct_qsvm_model(
|
88
|
-
train_data: DataList,
|
89
|
-
train_labels: LabelsInt,
|
90
|
-
test_data: DataList,
|
91
|
-
test_labels: LabelsInt,
|
92
|
-
predict_data: DataList,
|
93
|
-
feature_map_function_name: str,
|
94
|
-
**kwargs: Any,
|
95
|
-
) -> SerializedModel:
|
96
|
-
warnings.warn(
|
97
|
-
"Function 'construct_qsvm_model' has been deprecated and will no longer"
|
98
|
-
"be supported starting on 03/02/2025 the earliest\nHint: It is now possible to "
|
99
|
-
"implement QSVM in pure Qmod. For example, see the QSVM notebook on the "
|
100
|
-
"Classiq library at https://github.com/Classiq/classiq-library/blob/main/algorithms/qml/qsvm/qsvm.ipynb",
|
101
|
-
category=DeprecationWarning,
|
102
|
-
stacklevel=2,
|
103
|
-
)
|
104
|
-
qsvm_qmod = Model(
|
105
|
-
functions=[
|
106
|
-
NativeFunctionDefinition(
|
107
|
-
name="main",
|
108
|
-
positional_arg_declarations=[
|
109
|
-
PortDeclaration(
|
110
|
-
name="qbv",
|
111
|
-
direction=PortDeclarationDirection.Output,
|
112
|
-
),
|
113
|
-
],
|
114
|
-
body=get_qsvm_qmain_body(
|
115
|
-
feature_map_function_name=feature_map_function_name, **kwargs
|
116
|
-
),
|
117
|
-
),
|
118
|
-
],
|
119
|
-
classical_execution_code=f"""
|
120
|
-
{_OUTPUT_VARIABLE_NAME} = qsvm_full_run(
|
121
|
-
train_data={train_data},
|
122
|
-
train_labels={train_labels},
|
123
|
-
test_data={test_data},
|
124
|
-
test_labels={test_labels},
|
125
|
-
predict_data={predict_data}
|
126
|
-
)
|
127
|
-
save({{{_OUTPUT_VARIABLE_NAME!r}: {_OUTPUT_VARIABLE_NAME}}})
|
128
|
-
""".strip(),
|
129
|
-
)
|
130
|
-
|
131
|
-
return qsvm_qmod.get_model()
|
@@ -1,57 +0,0 @@
|
|
1
|
-
from collections.abc import Sequence
|
2
|
-
|
3
|
-
from classiq.interface.debug_info.debug_info import new_function_debug_info_by_node
|
4
|
-
from classiq.interface.model.classical_if import ClassicalIf
|
5
|
-
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
6
|
-
from classiq.interface.model.quantum_statement import QuantumStatement
|
7
|
-
|
8
|
-
from classiq.model_expansions.closure import FunctionClosure
|
9
|
-
from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
|
10
|
-
from classiq.model_expansions.scope import Scope
|
11
|
-
|
12
|
-
|
13
|
-
def _is_all_identity_calls(body: Sequence[QuantumStatement]) -> bool:
|
14
|
-
return all(
|
15
|
-
isinstance(stmt, QuantumFunctionCall) and stmt.func_name.lower() == "identity"
|
16
|
-
for stmt in body
|
17
|
-
)
|
18
|
-
|
19
|
-
|
20
|
-
class ClassicalIfEmitter(CallEmitter[ClassicalIf]):
|
21
|
-
def emit(self, classical_if: ClassicalIf, /) -> bool:
|
22
|
-
condition = self._interpreter.evaluate(classical_if.condition).as_type(bool)
|
23
|
-
op_name = "then" if condition else "else"
|
24
|
-
is_generative = classical_if.is_generative()
|
25
|
-
|
26
|
-
body: Sequence[QuantumStatement]
|
27
|
-
if is_generative:
|
28
|
-
if not classical_if.has_generative_block(op_name):
|
29
|
-
return True
|
30
|
-
context = self._expand_generative_context(classical_if, op_name, op_name)
|
31
|
-
context.blocks["body"] = context.blocks[op_name]
|
32
|
-
context.blocks.pop(op_name)
|
33
|
-
body = context.statements("body")
|
34
|
-
else:
|
35
|
-
body = classical_if.then if condition else classical_if.else_
|
36
|
-
|
37
|
-
if _is_all_identity_calls(body):
|
38
|
-
return True
|
39
|
-
|
40
|
-
if is_generative or not self._should_wrap(body):
|
41
|
-
for stmt in body:
|
42
|
-
if is_generative:
|
43
|
-
self._interpreter._builder.emit_statement(stmt)
|
44
|
-
else:
|
45
|
-
self._interpreter.emit_statement(stmt)
|
46
|
-
return True
|
47
|
-
|
48
|
-
then_else_func = FunctionClosure.create(
|
49
|
-
name=self._counted_name_allocator.allocate("then" if condition else "else"),
|
50
|
-
body=body,
|
51
|
-
scope=Scope(parent=self._current_scope),
|
52
|
-
lambda_external_vars=self._builder.current_block.captured_vars,
|
53
|
-
)
|
54
|
-
self._emit_quantum_function_call(
|
55
|
-
then_else_func, list(), new_function_debug_info_by_node(classical_if)
|
56
|
-
)
|
57
|
-
return True
|
@@ -1,62 +0,0 @@
|
|
1
|
-
from classiq.interface.debug_info.debug_info import new_function_debug_info_by_node
|
2
|
-
from classiq.interface.exceptions import ClassiqExpansionError
|
3
|
-
from classiq.interface.generator.expressions.expression import Expression
|
4
|
-
from classiq.interface.generator.functions.builtins.internal_operators import (
|
5
|
-
REPEAT_OPERATOR_NAME,
|
6
|
-
)
|
7
|
-
from classiq.interface.generator.functions.classical_type import Integer
|
8
|
-
from classiq.interface.model.classical_parameter_declaration import (
|
9
|
-
ClassicalParameterDeclaration,
|
10
|
-
)
|
11
|
-
from classiq.interface.model.repeat import Repeat
|
12
|
-
|
13
|
-
from classiq.model_expansions.closure import FunctionClosure, GenerativeFunctionClosure
|
14
|
-
from classiq.model_expansions.quantum_operations.call_emitter import CallEmitter
|
15
|
-
from classiq.model_expansions.scope import Scope
|
16
|
-
from classiq.qmod.quantum_function import GenerativeQFunc
|
17
|
-
|
18
|
-
|
19
|
-
class RepeatEmitter(CallEmitter[Repeat]):
|
20
|
-
def emit(self, repeat: Repeat, /) -> bool:
|
21
|
-
count = self._interpreter.evaluate(repeat.count).as_type(int)
|
22
|
-
if count < 0:
|
23
|
-
raise ClassiqExpansionError(
|
24
|
-
f"repeat count must be non-negative, got {count}"
|
25
|
-
)
|
26
|
-
op_name = self._counted_name_allocator.allocate(REPEAT_OPERATOR_NAME)
|
27
|
-
for i in range(count):
|
28
|
-
self._emit_iteration(repeat, i, op_name)
|
29
|
-
return True
|
30
|
-
|
31
|
-
def _emit_iteration(self, repeat: Repeat, i: int, op_name: str) -> None:
|
32
|
-
closure_constructor: type[FunctionClosure]
|
33
|
-
extra_args: dict
|
34
|
-
if repeat.is_generative():
|
35
|
-
closure_constructor = GenerativeFunctionClosure
|
36
|
-
extra_args = {
|
37
|
-
"generative_blocks": {
|
38
|
-
"body": GenerativeQFunc(
|
39
|
-
repeat.get_generative_block("body"),
|
40
|
-
),
|
41
|
-
}
|
42
|
-
}
|
43
|
-
else:
|
44
|
-
closure_constructor = FunctionClosure
|
45
|
-
extra_args = {}
|
46
|
-
iteration_function = closure_constructor.create(
|
47
|
-
name=op_name,
|
48
|
-
positional_arg_declarations=[
|
49
|
-
ClassicalParameterDeclaration(
|
50
|
-
name=repeat.iter_var, classical_type=Integer()
|
51
|
-
)
|
52
|
-
],
|
53
|
-
body=repeat.body,
|
54
|
-
scope=Scope(parent=self._current_scope),
|
55
|
-
lambda_external_vars=self._builder.current_block.captured_vars,
|
56
|
-
**extra_args,
|
57
|
-
)
|
58
|
-
self._emit_quantum_function_call(
|
59
|
-
iteration_function,
|
60
|
-
[Expression(expr=str(i))],
|
61
|
-
new_function_debug_info_by_node(repeat),
|
62
|
-
)
|
File without changes
|