classiq 0.86.1__py3-none-any.whl → 0.87.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 +2 -0
- classiq/applications/chemistry/hartree_fock.py +5 -1
- classiq/applications/chemistry/op_utils.py +2 -2
- classiq/applications/combinatorial_helpers/encoding_mapping.py +11 -15
- classiq/applications/combinatorial_helpers/encoding_utils.py +6 -6
- classiq/applications/combinatorial_helpers/memory.py +4 -4
- classiq/applications/combinatorial_helpers/optimization_model.py +5 -5
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +6 -10
- classiq/applications/combinatorial_helpers/pyomo_utils.py +27 -26
- classiq/applications/combinatorial_helpers/sympy_utils.py +2 -2
- classiq/applications/combinatorial_helpers/transformations/encoding.py +4 -6
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +4 -4
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +2 -2
- classiq/applications/combinatorial_helpers/transformations/penalty_support.py +3 -3
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -0
- classiq/applications/hamiltonian/pauli_decomposition.py +33 -1
- classiq/evaluators/argument_types.py +15 -6
- classiq/evaluators/parameter_types.py +43 -39
- classiq/evaluators/qmod_annotated_expression.py +88 -11
- classiq/evaluators/qmod_expression_visitors/out_of_place_node_transformer.py +19 -0
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +54 -11
- classiq/evaluators/qmod_expression_visitors/qmod_expression_renamer.py +40 -25
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +29 -59
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +12 -5
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +175 -28
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +21 -14
- classiq/evaluators/qmod_node_evaluators/compare_evaluation.py +9 -5
- classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +20 -1
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +97 -0
- classiq/evaluators/qmod_node_evaluators/name_evaluation.py +11 -26
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +56 -0
- classiq/evaluators/qmod_node_evaluators/piecewise_evaluation.py +40 -0
- classiq/evaluators/qmod_node_evaluators/struct_instantiation_evaluation.py +2 -3
- classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +48 -21
- classiq/evaluators/qmod_node_evaluators/unary_op_evaluation.py +53 -9
- classiq/evaluators/qmod_node_evaluators/utils.py +27 -5
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +188 -0
- classiq/evaluators/qmod_type_inference/quantum_type_inference.py +292 -0
- classiq/evaluators/quantum_type_utils.py +0 -131
- classiq/execution/execution_session.py +1 -1
- classiq/execution/qnn.py +4 -1
- classiq/execution/user_budgets.py +1 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +10 -30
- classiq/interface/backend/quantum_backend_providers.py +63 -52
- classiq/interface/generator/arith/binary_ops.py +107 -115
- classiq/interface/generator/arith/extremum_operations.py +33 -45
- classiq/interface/generator/arith/number_utils.py +4 -1
- classiq/interface/generator/circuit_code/types_and_constants.py +0 -9
- classiq/interface/generator/compiler_keywords.py +2 -0
- classiq/interface/generator/function_param_list.py +133 -5
- classiq/interface/generator/functions/classical_type.py +59 -2
- classiq/interface/generator/functions/qmod_python_interface.py +15 -0
- classiq/interface/generator/functions/type_name.py +6 -0
- classiq/interface/generator/model/preferences/preferences.py +1 -17
- classiq/interface/generator/quantum_program.py +1 -13
- classiq/interface/helpers/model_normalizer.py +2 -2
- classiq/interface/helpers/text_utils.py +7 -2
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/classical_if.py +40 -0
- classiq/interface/model/handle_binding.py +28 -16
- classiq/interface/model/quantum_type.py +61 -2
- classiq/interface/pretty_print/expression_to_qmod.py +24 -11
- classiq/interface/pyomo_extension/__init__.py +0 -4
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +2 -2
- classiq/model_expansions/arithmetic.py +43 -1
- classiq/model_expansions/arithmetic_compute_result_attrs.py +255 -0
- classiq/model_expansions/capturing/captured_vars.py +2 -5
- classiq/model_expansions/quantum_operations/allocate.py +22 -15
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -3
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +52 -71
- classiq/model_expansions/quantum_operations/bind.py +15 -7
- classiq/model_expansions/quantum_operations/call_emitter.py +2 -10
- classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -0
- classiq/open_library/functions/__init__.py +3 -0
- classiq/open_library/functions/lcu.py +117 -0
- classiq/qmod/builtins/enums.py +2 -2
- classiq/qmod/builtins/structs.py +33 -18
- classiq/qmod/pretty_print/expression_to_python.py +7 -9
- {classiq-0.86.1.dist-info → classiq-0.87.0.dist-info}/METADATA +3 -3
- {classiq-0.86.1.dist-info → classiq-0.87.0.dist-info}/RECORD +83 -89
- classiq/interface/generator/amplitude_estimation.py +0 -34
- classiq/interface/generator/function_param_list_without_self_reference.py +0 -160
- classiq/interface/generator/grover_diffuser.py +0 -93
- classiq/interface/generator/grover_operator.py +0 -106
- classiq/interface/generator/oracles/__init__.py +0 -3
- classiq/interface/generator/oracles/arithmetic_oracle.py +0 -82
- classiq/interface/generator/oracles/custom_oracle.py +0 -65
- classiq/interface/generator/oracles/oracle_abc.py +0 -76
- classiq/interface/generator/oracles/oracle_function_param_list.py +0 -6
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +0 -165
- classiq/interface/generator/qpe.py +0 -169
- classiq/interface/grover/grover_modelling_params.py +0 -13
- classiq/model_expansions/transformers/var_splitter.py +0 -224
- /classiq/{interface/grover → evaluators/qmod_type_inference}/__init__.py +0 -0
- {classiq-0.86.1.dist-info → classiq-0.87.0.dist-info}/WHEEL +0 -0
@@ -209,23 +209,6 @@ class AwsBackendPreferences(BackendPreferences):
|
|
209
209
|
)
|
210
210
|
|
211
211
|
|
212
|
-
class IBMBackendProvider(BaseModel):
|
213
|
-
"""
|
214
|
-
|
215
|
-
Represents the provider specs for identifying an IBM Quantum backend.
|
216
|
-
|
217
|
-
Attributes:
|
218
|
-
hub (str): hub parameter of IBM Quantum provider. Defaults to `"ibm-q"`.
|
219
|
-
group (str): group parameter of IBM Quantum provider. Defaults to `"open"`.
|
220
|
-
project (str): project parameter of IBM Quantum provider. Defaults to `"main"`.
|
221
|
-
|
222
|
-
"""
|
223
|
-
|
224
|
-
hub: str = "ibm-q"
|
225
|
-
group: str = "open"
|
226
|
-
project: str = "main"
|
227
|
-
|
228
|
-
|
229
212
|
class IBMBackendPreferences(BackendPreferences):
|
230
213
|
"""
|
231
214
|
Represents the backend preferences specific to IBM Quantum services.
|
@@ -234,30 +217,28 @@ class IBMBackendPreferences(BackendPreferences):
|
|
234
217
|
specific to IBM Quantum backends.
|
235
218
|
|
236
219
|
Attributes:
|
237
|
-
backend_service_provider (ProviderTypeVendor.
|
238
|
-
access_token (Optional[str]): The IBM
|
239
|
-
|
240
|
-
|
220
|
+
backend_service_provider (ProviderTypeVendor.IBM_CLOUD): Indicates the backend service provider as IBM Cloud.
|
221
|
+
access_token (Optional[str]): The IBM Cloud access token to be used with IBM Quantum hosted backends. Defaults to `None`.
|
222
|
+
channel (str): Channel to use for IBM cloud backends. Defaults to `"ibm_cloud"`.
|
223
|
+
instance_crn (str): The IBM Cloud instance CRN (Cloud Resource Name) for the IBM Quantum service.
|
241
224
|
run_through_classiq (bool): Run through Classiq's credentials. Defaults to `False`.
|
242
225
|
|
243
226
|
See examples in the [IBM Quantum Backend Documentation](https://docs.classiq.io/latest/reference-manual/executor/cloud-providers/ibm-backends/?h=).
|
244
227
|
"""
|
245
228
|
|
246
|
-
backend_service_provider: ProviderTypeVendor.
|
229
|
+
backend_service_provider: ProviderTypeVendor.IBM_CLOUD = pydantic.Field(
|
247
230
|
default=ProviderVendor.IBM_QUANTUM
|
248
231
|
)
|
249
232
|
access_token: Optional[str] = pydantic.Field(
|
250
233
|
default=None,
|
251
|
-
description="IBM
|
234
|
+
description="IBM Cloud access token to be used"
|
252
235
|
" with IBM Quantum hosted backends",
|
253
236
|
)
|
254
|
-
|
255
|
-
|
256
|
-
description="Provider specs. for identifying a single IBM Quantum provider.",
|
237
|
+
channel: Optional[str] = pydantic.Field(
|
238
|
+
default=None, description="Channel to use for IBM cloud backends."
|
257
239
|
)
|
258
|
-
|
259
|
-
default=None,
|
260
|
-
description="QCTRL API key to access QCTRL optimization abilities",
|
240
|
+
instance_crn: Optional[str] = pydantic.Field(
|
241
|
+
default=None, description="IBM Cloud instance CRN."
|
261
242
|
)
|
262
243
|
run_through_classiq: bool = pydantic.Field(
|
263
244
|
default=False,
|
@@ -544,7 +525,6 @@ __all__ = [
|
|
544
525
|
"ClassiqSimulatorBackendNames",
|
545
526
|
"GCPBackendPreferences",
|
546
527
|
"IBMBackendPreferences",
|
547
|
-
"IBMBackendProvider",
|
548
528
|
"IQCCBackendPreferences",
|
549
529
|
"IntelBackendNames",
|
550
530
|
"IntelBackendPreferences",
|
@@ -26,7 +26,7 @@ class ProviderVendor(StrEnum):
|
|
26
26
|
|
27
27
|
class ProviderTypeVendor:
|
28
28
|
CLASSIQ = Literal[ProviderVendor.CLASSIQ]
|
29
|
-
|
29
|
+
IBM_CLOUD = Literal[ProviderVendor.IBM_QUANTUM]
|
30
30
|
AZURE_QUANTUM = Literal[ProviderVendor.AZURE_QUANTUM]
|
31
31
|
AMAZON_BRAKET = Literal[ProviderVendor.AMAZON_BRAKET]
|
32
32
|
IONQ = Literal[ProviderVendor.IONQ]
|
@@ -108,63 +108,74 @@ class AmazonBraketBackendNames(StrEnum):
|
|
108
108
|
|
109
109
|
|
110
110
|
# The IBM devices were taken from:
|
111
|
-
# from
|
112
|
-
# provider =
|
111
|
+
# from qiskit_ibm_runtime.fake_provider import FakeProviderForBackendV2
|
112
|
+
# provider = FakeProviderForBackendV2()
|
113
113
|
# backends_list = provider.backends()
|
114
|
-
#
|
115
|
-
# the_devices = [_normalize_backend_name(str(backend)) for backend in backends_list]
|
114
|
+
# the_devices = ["ibm_" + backend.name.split('_')[1] for backend in backends_list.backends()]
|
116
115
|
class IBMQHardwareNames(StrEnum):
|
117
116
|
"""
|
118
117
|
IBM backend names which Classiq Supports running on.
|
119
118
|
"""
|
120
119
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
120
|
+
IBM_ALGIERS = "ibm_algiers"
|
121
|
+
IBM_ALMADEN = "ibm_almaden"
|
122
|
+
IBM_ARMONK = "ibm_armonk"
|
123
|
+
IBM_ATHENS = "ibm_athens"
|
124
|
+
IBM_AUCKLAND = "ibm_auckland"
|
125
|
+
IBM_BELEM = "ibm_belem"
|
126
|
+
IBM_BOEBLINGEN = "ibm_boeblingen"
|
127
|
+
IBM_BOGOTA = "ibm_bogota"
|
128
|
+
IBM_BRISBANE = "ibm_brisbane"
|
129
|
+
IBM_BROOKLYN = "ibm_brooklyn"
|
130
|
+
IBM_BURLINGTON = "ibm_burlington"
|
131
|
+
IBM_CAIRO = "ibm_cairo"
|
132
|
+
IBM_CAMBRIDGE = "ibm_cambridge"
|
133
|
+
IBM_CASABLANCA = "ibm_casablanca"
|
134
|
+
IBM_CUSCO = "ibm_cusco"
|
135
|
+
IBM_ESSEX = "ibm_essex"
|
136
|
+
IBM_FEZ = "ibm_fez"
|
137
|
+
IBM_FRACTIONAL = "ibm_fractional"
|
138
|
+
IBM_GENEVA = "ibm_geneva"
|
139
|
+
IBM_GUADALUPE = "ibm_guadalupe"
|
140
|
+
IBM_HANOI = "ibm_hanoi"
|
141
|
+
IBM_JAKARTA = "ibm_jakarta"
|
142
|
+
IBM_JOHANNESBURG = "ibm_johannesburg"
|
143
|
+
IBM_KAWASAKI = "ibm_kawasaki"
|
144
|
+
IBM_KOLKATA = "ibm_kolkata"
|
145
|
+
IBM_KYIV = "ibm_kyiv"
|
146
|
+
IBM_KYOTO = "ibm_kyoto"
|
147
|
+
IBM_LAGOS = "ibm_lagos"
|
148
|
+
IBM_LIMA = "ibm_lima"
|
149
|
+
IBM_LONDON = "ibm_london"
|
150
|
+
IBM_MANHATTAN = "ibm_manhattan"
|
151
|
+
IBM_MANILA = "ibm_manila"
|
152
|
+
IBM_MELBOURNE = "ibm_melbourne"
|
153
|
+
IBM_MARRAKESH = "ibm_marrakesh"
|
154
|
+
IBM_MONTREAL = "ibm_montreal"
|
155
|
+
IBM_MUMBAI = "ibm_mumbai"
|
156
|
+
IBM_NAIROBI = "ibm_nairobi"
|
157
|
+
IBM_OSAKA = "ibm_osaka"
|
158
|
+
IBM_OSLO = "ibm_oslo"
|
159
|
+
IBM_OURENSE = "ibm_ourense"
|
160
|
+
IBM_PARIS = "ibm_paris"
|
161
|
+
IBM_PEEKSKILL = "ibm_peekskill"
|
162
|
+
IBM_PERTH = "ibm_perth"
|
163
|
+
IBM_PRAGUE = "ibm_prague"
|
164
|
+
IBM_POUGHKEEPSIE = "ibm_poughkeepsie"
|
165
|
+
IBM_QUEBEC = "ibm_quebec"
|
166
|
+
IBM_QUITO = "ibm_quito"
|
167
|
+
IBM_ROCHESTER = "ibm_rochester"
|
168
|
+
IBM_ROME = "ibm_rome"
|
169
|
+
IBM_SANTIAGO = "ibm_santiago"
|
170
|
+
IBM_SHERBROOKE = "ibm_sherbrooke"
|
171
|
+
IBM_SINGAPORE = "ibm_singapore"
|
172
|
+
IBM_SYDNEY = "ibm_sydney"
|
173
|
+
IBM_TORINO = "ibm_torino"
|
174
|
+
IBM_TORONTO = "ibm_toronto"
|
175
|
+
IBM_VALENCIA = "ibm_valencia"
|
176
|
+
IBM_VIGO = "ibm_vigo"
|
177
|
+
IBM_WASHINGTON = "ibm_washington"
|
178
|
+
IBM_YORKTOWN = "ibm_yorktown"
|
168
179
|
|
169
180
|
|
170
181
|
class ClassiqNvidiaBackendNames(StrEnum):
|
@@ -36,6 +36,14 @@ from classiq.model_expansions.arithmetic import NumericAttributes
|
|
36
36
|
from classiq.model_expansions.arithmetic_compute_result_attrs import (
|
37
37
|
compute_result_attrs_add,
|
38
38
|
compute_result_attrs_assign,
|
39
|
+
compute_result_attrs_bitwise_and,
|
40
|
+
compute_result_attrs_bitwise_or,
|
41
|
+
compute_result_attrs_bitwise_xor,
|
42
|
+
compute_result_attrs_lshift,
|
43
|
+
compute_result_attrs_modulo,
|
44
|
+
compute_result_attrs_multiply,
|
45
|
+
compute_result_attrs_power,
|
46
|
+
compute_result_attrs_rshift,
|
39
47
|
compute_result_attrs_subtract,
|
40
48
|
)
|
41
49
|
|
@@ -225,31 +233,6 @@ class BinaryOpWithIntInputs(BinaryOpParams[RegisterOrInt, RegisterOrInt]):
|
|
225
233
|
raise ClassiqValueError(BOOLEAN_OP_WITH_FRACTIONS_ERROR)
|
226
234
|
return self
|
227
235
|
|
228
|
-
@staticmethod
|
229
|
-
def _is_signed(arg: Union[int, RegisterArithmeticInfo]) -> bool:
|
230
|
-
if isinstance(arg, RegisterArithmeticInfo):
|
231
|
-
return arg.is_signed
|
232
|
-
return arg < 0
|
233
|
-
|
234
|
-
def _get_result_register(self) -> RegisterArithmeticInfo:
|
235
|
-
required_size = self._aligned_inputs_max_length()
|
236
|
-
is_signed = self._include_sign and (
|
237
|
-
self._is_signed(self.left_arg) or self._is_signed(self.right_arg)
|
238
|
-
)
|
239
|
-
return RegisterArithmeticInfo(
|
240
|
-
size=self.output_size or required_size, is_signed=is_signed
|
241
|
-
)
|
242
|
-
|
243
|
-
def _aligned_inputs_max_length(self) -> int:
|
244
|
-
left_signed: bool = argument_utils.is_signed(self.left_arg)
|
245
|
-
right_signed: bool = argument_utils.is_signed(self.right_arg)
|
246
|
-
return max(
|
247
|
-
argument_utils.integer_part_size(self.right_arg)
|
248
|
-
+ int(left_signed and not right_signed),
|
249
|
-
argument_utils.integer_part_size(self.left_arg)
|
250
|
-
+ int(right_signed and not left_signed),
|
251
|
-
)
|
252
|
-
|
253
236
|
|
254
237
|
class BinaryOpWithFloatInputs(BinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
255
238
|
pass
|
@@ -258,10 +241,42 @@ class BinaryOpWithFloatInputs(BinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
|
258
241
|
class BitwiseAnd(BinaryOpWithIntInputs):
|
259
242
|
output_name = "bitwise_and"
|
260
243
|
|
244
|
+
def _get_result_register(self) -> RegisterArithmeticInfo:
|
245
|
+
left_attrs = NumericAttributes.from_type_or_constant(
|
246
|
+
self.left_arg, self.machine_precision
|
247
|
+
)
|
248
|
+
right_attrs = NumericAttributes.from_type_or_constant(
|
249
|
+
self.right_arg, self.machine_precision
|
250
|
+
)
|
251
|
+
result_attrs = compute_result_attrs_bitwise_and(
|
252
|
+
left_attrs, right_attrs, self.machine_precision
|
253
|
+
)
|
254
|
+
return RegisterArithmeticInfo(
|
255
|
+
size=self.output_size or result_attrs.size,
|
256
|
+
is_signed=self._include_sign and result_attrs.is_signed,
|
257
|
+
fraction_places=result_attrs.fraction_digits,
|
258
|
+
)
|
259
|
+
|
261
260
|
|
262
261
|
class BitwiseOr(BinaryOpWithIntInputs):
|
263
262
|
output_name = "bitwise_or"
|
264
263
|
|
264
|
+
def _get_result_register(self) -> RegisterArithmeticInfo:
|
265
|
+
left_attrs = NumericAttributes.from_type_or_constant(
|
266
|
+
self.left_arg, self.machine_precision
|
267
|
+
)
|
268
|
+
right_attrs = NumericAttributes.from_type_or_constant(
|
269
|
+
self.right_arg, self.machine_precision
|
270
|
+
)
|
271
|
+
result_attrs = compute_result_attrs_bitwise_or(
|
272
|
+
left_attrs, right_attrs, self.machine_precision
|
273
|
+
)
|
274
|
+
return RegisterArithmeticInfo(
|
275
|
+
size=self.output_size or result_attrs.size,
|
276
|
+
is_signed=self._include_sign and result_attrs.is_signed,
|
277
|
+
fraction_places=result_attrs.fraction_digits,
|
278
|
+
)
|
279
|
+
|
265
280
|
|
266
281
|
# TODO: fix diamond inheritance
|
267
282
|
class BitwiseXor(
|
@@ -269,6 +284,22 @@ class BitwiseXor(
|
|
269
284
|
):
|
270
285
|
output_name = "bitwise_xor"
|
271
286
|
|
287
|
+
def _get_result_register(self) -> RegisterArithmeticInfo:
|
288
|
+
left_attrs = NumericAttributes.from_type_or_constant(
|
289
|
+
self.left_arg, self.machine_precision
|
290
|
+
)
|
291
|
+
right_attrs = NumericAttributes.from_type_or_constant(
|
292
|
+
self.right_arg, self.machine_precision
|
293
|
+
)
|
294
|
+
result_attrs = compute_result_attrs_bitwise_xor(
|
295
|
+
left_attrs, right_attrs, self.machine_precision
|
296
|
+
)
|
297
|
+
return RegisterArithmeticInfo(
|
298
|
+
size=self.output_size or result_attrs.size,
|
299
|
+
is_signed=self._include_sign and result_attrs.is_signed,
|
300
|
+
fraction_places=result_attrs.fraction_digits,
|
301
|
+
)
|
302
|
+
|
272
303
|
|
273
304
|
class Adder(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
|
274
305
|
output_name = "sum"
|
@@ -467,29 +498,18 @@ class Multiplier(BinaryOpWithFloatInputs):
|
|
467
498
|
argument_utils.limit_fraction_places(self.right_arg, self.machine_precision)
|
468
499
|
)
|
469
500
|
|
470
|
-
@staticmethod
|
471
|
-
def _get_bounds(
|
472
|
-
args: tuple[RegisterOrConst, RegisterOrConst], machine_precision: int
|
473
|
-
) -> tuple[float, float]:
|
474
|
-
extremal_values = [
|
475
|
-
left * right
|
476
|
-
for left in argument_utils.bounds(args[0])
|
477
|
-
for right in argument_utils.bounds(args[1])
|
478
|
-
]
|
479
|
-
return (
|
480
|
-
number_utils.limit_fraction_places(min(extremal_values), machine_precision),
|
481
|
-
number_utils.limit_fraction_places(max(extremal_values), machine_precision),
|
482
|
-
)
|
483
|
-
|
484
501
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
485
|
-
|
486
|
-
left_arg = argument_utils.limit_fraction_places(
|
502
|
+
left_attrs = NumericAttributes.from_type_or_constant(
|
487
503
|
self.left_arg, self.machine_precision
|
488
504
|
)
|
489
|
-
|
505
|
+
right_attrs = NumericAttributes.from_type_or_constant(
|
490
506
|
self.right_arg, self.machine_precision
|
491
507
|
)
|
492
|
-
|
508
|
+
result_attrs = compute_result_attrs_multiply(
|
509
|
+
left_attrs, right_attrs, self.machine_precision
|
510
|
+
)
|
511
|
+
fraction_places = result_attrs.fraction_digits
|
512
|
+
bounds = result_attrs.bounds
|
493
513
|
if self.output_size:
|
494
514
|
if fraction_places:
|
495
515
|
raise ValueError(MODULO_WITH_FRACTION_PLACES_ERROR_MSG)
|
@@ -498,10 +518,8 @@ class Multiplier(BinaryOpWithFloatInputs):
|
|
498
518
|
)
|
499
519
|
bounds = number_utils.bounds_cut(bounds, max_bounds)
|
500
520
|
|
501
|
-
size = self.output_size or
|
502
|
-
|
503
|
-
)
|
504
|
-
is_signed = self._include_sign and min(bounds) < 0
|
521
|
+
size = self.output_size or result_attrs.size
|
522
|
+
is_signed = self._include_sign and result_attrs.is_signed
|
505
523
|
return RegisterArithmeticInfo(
|
506
524
|
size=size,
|
507
525
|
fraction_places=fraction_places,
|
@@ -514,25 +532,6 @@ class Multiplier(BinaryOpWithFloatInputs):
|
|
514
532
|
),
|
515
533
|
)
|
516
534
|
|
517
|
-
@staticmethod
|
518
|
-
def _get_output_size(
|
519
|
-
bounds: tuple[float, float],
|
520
|
-
fraction_places: int,
|
521
|
-
left_arg: Union[RegisterArithmeticInfo, float],
|
522
|
-
right_arg: Union[RegisterArithmeticInfo, float],
|
523
|
-
) -> int:
|
524
|
-
if isinstance(left_arg, float) and left_arg == 1.0:
|
525
|
-
assert isinstance(right_arg, RegisterArithmeticInfo)
|
526
|
-
return right_arg.size
|
527
|
-
elif isinstance(right_arg, float) and right_arg == 1.0:
|
528
|
-
assert isinstance(left_arg, RegisterArithmeticInfo)
|
529
|
-
return left_arg.size
|
530
|
-
if bounds[0] == 0 and bounds[1] == 0:
|
531
|
-
return max(1, fraction_places)
|
532
|
-
|
533
|
-
integer_part_size = number_utils.bounds_to_integer_part_size(*bounds)
|
534
|
-
return integer_part_size + fraction_places
|
535
|
-
|
536
535
|
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
537
536
|
return max(
|
538
537
|
0, self.expected_fraction_places() - self.result_register.fraction_places
|
@@ -592,43 +591,22 @@ class Power(BinaryOpParams[RegisterArithmeticInfo, pydantic.PositiveInt]):
|
|
592
591
|
* self.right_arg
|
593
592
|
)
|
594
593
|
|
595
|
-
def _get_result_bounds(self) -> tuple[float, float]:
|
596
|
-
bounds = [
|
597
|
-
number_utils.limit_fraction_places(
|
598
|
-
bound, machine_precision=self.machine_precision
|
599
|
-
)
|
600
|
-
for bound in self.left_arg.bounds
|
601
|
-
]
|
602
|
-
if (self.right_arg % 2) or min(bounds) >= 0 or max(bounds) <= 0:
|
603
|
-
return (
|
604
|
-
number_utils.limit_fraction_places(
|
605
|
-
bounds[0] ** self.right_arg,
|
606
|
-
machine_precision=self.machine_precision,
|
607
|
-
),
|
608
|
-
number_utils.limit_fraction_places(
|
609
|
-
bounds[1] ** self.right_arg,
|
610
|
-
machine_precision=self.machine_precision,
|
611
|
-
),
|
612
|
-
)
|
613
|
-
return 0.0, number_utils.limit_fraction_places(
|
614
|
-
max(abs(bound) for bound in bounds) ** self.right_arg,
|
615
|
-
machine_precision=self.machine_precision,
|
616
|
-
)
|
617
|
-
|
618
594
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
619
595
|
if self.output_size:
|
620
596
|
return RegisterArithmeticInfo(size=self.output_size)
|
621
597
|
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
598
|
+
left_attrs = NumericAttributes.from_register_arithmetic_info(
|
599
|
+
self.left_arg, self.machine_precision
|
600
|
+
)
|
601
|
+
result_attrs = compute_result_attrs_power(
|
602
|
+
left_attrs, self.right_arg, self.machine_precision
|
603
|
+
)
|
604
|
+
|
627
605
|
return RegisterArithmeticInfo(
|
628
|
-
size=size,
|
629
|
-
is_signed=
|
630
|
-
fraction_places=
|
631
|
-
bounds=bounds,
|
606
|
+
size=result_attrs.size,
|
607
|
+
is_signed=result_attrs.is_signed,
|
608
|
+
fraction_places=result_attrs.fraction_digits,
|
609
|
+
bounds=result_attrs.bounds,
|
632
610
|
)
|
633
611
|
|
634
612
|
def _get_inner_action_garbage_size(
|
@@ -709,13 +687,17 @@ class LShift(EffectiveUnaryOpParams[pydantic.NonNegativeInt]):
|
|
709
687
|
return max(self.left_arg.size + extra_result_lsbs - self.output_size, 0)
|
710
688
|
|
711
689
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
712
|
-
|
713
|
-
|
714
|
-
|
690
|
+
left_attrs = NumericAttributes.from_register_arithmetic_info(
|
691
|
+
self.left_arg, self.machine_precision
|
692
|
+
)
|
693
|
+
result_attrs = compute_result_attrs_lshift(
|
694
|
+
left_attrs, self.right_arg, self.machine_precision
|
695
|
+
)
|
715
696
|
return RegisterArithmeticInfo(
|
716
|
-
size=self.output_size or
|
717
|
-
is_signed=self._include_sign and
|
718
|
-
fraction_places=
|
697
|
+
size=self.output_size or result_attrs.size,
|
698
|
+
is_signed=self._include_sign and result_attrs.is_signed,
|
699
|
+
fraction_places=result_attrs.fraction_digits,
|
700
|
+
bounds=result_attrs.bounds if not self.output_size else None,
|
719
701
|
)
|
720
702
|
|
721
703
|
|
@@ -755,15 +737,17 @@ class RShift(EffectiveUnaryOpParams[pydantic.NonNegativeInt]):
|
|
755
737
|
)
|
756
738
|
|
757
739
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
758
|
-
|
759
|
-
|
760
|
-
|
740
|
+
left_attrs = NumericAttributes.from_register_arithmetic_info(
|
741
|
+
self.left_arg, self.machine_precision
|
742
|
+
)
|
743
|
+
result_attrs = compute_result_attrs_rshift(
|
744
|
+
left_attrs, self.right_arg, self.machine_precision
|
761
745
|
)
|
762
|
-
required_size = max(min_size, new_fraction_places)
|
763
746
|
return RegisterArithmeticInfo(
|
764
|
-
size=self.output_size or
|
765
|
-
is_signed=self._include_sign and
|
766
|
-
fraction_places=
|
747
|
+
size=self.output_size or result_attrs.size,
|
748
|
+
is_signed=self._include_sign and result_attrs.is_signed,
|
749
|
+
fraction_places=result_attrs.fraction_digits,
|
750
|
+
bounds=result_attrs.bounds if not self.output_size else None,
|
767
751
|
)
|
768
752
|
|
769
753
|
|
@@ -822,7 +806,15 @@ class Modulo(EffectiveUnaryOpParams[int]):
|
|
822
806
|
return 2 ** (repr_qubits)
|
823
807
|
|
824
808
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
809
|
+
left_attrs = NumericAttributes.from_register_arithmetic_info(
|
810
|
+
self.left_arg, self.machine_precision
|
811
|
+
)
|
812
|
+
result_attrs = compute_result_attrs_modulo(
|
813
|
+
left_attrs, self.right_arg, self.machine_precision
|
814
|
+
)
|
815
|
+
return RegisterArithmeticInfo(
|
816
|
+
size=result_attrs.size,
|
817
|
+
is_signed=result_attrs.is_signed,
|
818
|
+
fraction_places=result_attrs.fraction_digits,
|
819
|
+
bounds=result_attrs.bounds,
|
820
|
+
)
|
@@ -18,6 +18,12 @@ from classiq.interface.generator.arith.binary_ops import (
|
|
18
18
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
19
19
|
from classiq.interface.generator.function_params import get_zero_input_name
|
20
20
|
|
21
|
+
from classiq.model_expansions.arithmetic import NumericAttributes
|
22
|
+
from classiq.model_expansions.arithmetic_compute_result_attrs import (
|
23
|
+
compute_result_attrs_max,
|
24
|
+
compute_result_attrs_min,
|
25
|
+
)
|
26
|
+
|
21
27
|
Numeric = (float, int)
|
22
28
|
|
23
29
|
|
@@ -55,11 +61,6 @@ class Extremum(ArithmeticOperationParams):
|
|
55
61
|
def get_params_inplace_options(self) -> Iterable["Extremum"]:
|
56
62
|
return ()
|
57
63
|
|
58
|
-
@classmethod
|
59
|
-
@abc.abstractmethod
|
60
|
-
def _bound_calculator(cls, arg1: float, arg2: float) -> float:
|
61
|
-
pass
|
62
|
-
|
63
64
|
@staticmethod
|
64
65
|
def _less_qubits_arg(
|
65
66
|
arg1: RegisterOrConst, arg2: RegisterOrConst
|
@@ -78,40 +79,15 @@ class Extremum(ArithmeticOperationParams):
|
|
78
79
|
pass
|
79
80
|
|
80
81
|
def _get_result_register(self) -> RegisterArithmeticInfo:
|
81
|
-
|
82
|
+
left_attrs = NumericAttributes.from_type_or_constant(
|
82
83
|
self.left_arg, self.machine_precision
|
83
84
|
)
|
84
|
-
|
85
|
+
right_attrs = NumericAttributes.from_type_or_constant(
|
85
86
|
self.right_arg, self.machine_precision
|
86
87
|
)
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
self.preferred_arg(eff_left_arg, eff_right_arg)
|
91
|
-
)
|
92
|
-
|
93
|
-
def _get_general_case_result_register(
|
94
|
-
self, eff_left_arg: RegisterOrConst, eff_right_arg: RegisterOrConst
|
95
|
-
) -> RegisterArithmeticInfo:
|
96
|
-
integer_part_size = max(
|
97
|
-
argument_utils.integer_part_size(eff_left_arg),
|
98
|
-
argument_utils.integer_part_size(eff_right_arg),
|
99
|
-
)
|
100
|
-
fraction_places = max(
|
101
|
-
argument_utils.fraction_places(eff_left_arg),
|
102
|
-
argument_utils.fraction_places(eff_right_arg),
|
103
|
-
)
|
104
|
-
required_size = integer_part_size + fraction_places
|
105
|
-
bounds = (
|
106
|
-
self._bound_calculator(
|
107
|
-
argument_utils.lower_bound(eff_left_arg),
|
108
|
-
argument_utils.lower_bound(eff_right_arg),
|
109
|
-
),
|
110
|
-
self._bound_calculator(
|
111
|
-
argument_utils.upper_bound(eff_left_arg),
|
112
|
-
argument_utils.upper_bound(eff_right_arg),
|
113
|
-
),
|
114
|
-
)
|
88
|
+
result_attrs = self._compute_result_attrs(left_attrs, right_attrs)
|
89
|
+
bounds = result_attrs.bounds
|
90
|
+
fraction_places = result_attrs.fraction_digits
|
115
91
|
if self.output_size:
|
116
92
|
if fraction_places:
|
117
93
|
raise ValueError(MODULO_WITH_FRACTION_PLACES_ERROR_MSG)
|
@@ -119,8 +95,8 @@ class Extremum(ArithmeticOperationParams):
|
|
119
95
|
size=self.output_size, is_signed=False, fraction_places=0
|
120
96
|
)
|
121
97
|
bounds = number_utils.bounds_cut(bounds, max_bounds)
|
122
|
-
size = self.output_size or
|
123
|
-
is_signed = self._include_sign and
|
98
|
+
size = self.output_size or result_attrs.size
|
99
|
+
is_signed = self._include_sign and result_attrs.is_signed
|
124
100
|
return RegisterArithmeticInfo(
|
125
101
|
size=size,
|
126
102
|
fraction_places=fraction_places,
|
@@ -133,14 +109,16 @@ class Extremum(ArithmeticOperationParams):
|
|
133
109
|
),
|
134
110
|
)
|
135
111
|
|
112
|
+
@abc.abstractmethod
|
113
|
+
def _compute_result_attrs(
|
114
|
+
self, left_attrs: NumericAttributes, right_attrs: NumericAttributes
|
115
|
+
) -> NumericAttributes:
|
116
|
+
pass
|
117
|
+
|
136
118
|
|
137
119
|
class Min(Extremum):
|
138
120
|
output_name = "min_value"
|
139
121
|
|
140
|
-
@classmethod
|
141
|
-
def _bound_calculator(cls, arg1: float, arg2: float) -> float:
|
142
|
-
return min(arg1, arg2)
|
143
|
-
|
144
122
|
@classmethod
|
145
123
|
def preferred_arg(
|
146
124
|
cls, arg1: RegisterOrConst, arg2: RegisterOrConst
|
@@ -152,14 +130,17 @@ class Min(Extremum):
|
|
152
130
|
return arg2
|
153
131
|
return cls._less_qubits_arg(arg1, arg2)
|
154
132
|
|
133
|
+
def _compute_result_attrs(
|
134
|
+
self, left_attrs: NumericAttributes, right_attrs: NumericAttributes
|
135
|
+
) -> NumericAttributes:
|
136
|
+
return compute_result_attrs_min(
|
137
|
+
[left_attrs, right_attrs], self.machine_precision
|
138
|
+
)
|
139
|
+
|
155
140
|
|
156
141
|
class Max(Extremum):
|
157
142
|
output_name = "max_value"
|
158
143
|
|
159
|
-
@classmethod
|
160
|
-
def _bound_calculator(cls, arg1: float, arg2: float) -> float:
|
161
|
-
return max(arg1, arg2)
|
162
|
-
|
163
144
|
@classmethod
|
164
145
|
def preferred_arg(
|
165
146
|
cls, arg1: RegisterOrConst, arg2: RegisterOrConst
|
@@ -170,3 +151,10 @@ class Max(Extremum):
|
|
170
151
|
if max2 > max1:
|
171
152
|
return arg2
|
172
153
|
return cls._less_qubits_arg(arg1, arg2)
|
154
|
+
|
155
|
+
def _compute_result_attrs(
|
156
|
+
self, left_attrs: NumericAttributes, right_attrs: NumericAttributes
|
157
|
+
) -> NumericAttributes:
|
158
|
+
return compute_result_attrs_max(
|
159
|
+
[left_attrs, right_attrs], self.machine_precision
|
160
|
+
)
|
@@ -105,7 +105,10 @@ def bounds_to_attributes(
|
|
105
105
|
lb: float, ub: float, fraction_places: int, machine_precision: int
|
106
106
|
) -> tuple[int, bool, int]:
|
107
107
|
fraction_places = min(fraction_places, machine_precision)
|
108
|
-
|
108
|
+
if lb == ub == 0:
|
109
|
+
integers = 0
|
110
|
+
else:
|
111
|
+
integers = bounds_to_integer_part_size(lb, ub)
|
109
112
|
return max(1, integers + fraction_places), lb < 0, fraction_places
|
110
113
|
|
111
114
|
|