classiq 0.104.0__py3-none-any.whl → 1.0.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/_internals/authentication/auth0.py +29 -0
- classiq/_internals/authentication/auth_flow_factory.py +43 -0
- classiq/_internals/authentication/machine_credentials_flow.py +26 -0
- classiq/_internals/authentication/password_manager.py +84 -0
- classiq/_internals/authentication/token_manager.py +24 -8
- classiq/analyzer/show_interactive_hack.py +0 -8
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +1 -1
- classiq/execution/all_hardware_devices.py +59 -1
- classiq/execution/functions/__init__.py +11 -1
- classiq/execution/functions/expectation_value.py +106 -0
- classiq/execution/functions/minimize.py +90 -0
- classiq/execution/functions/sample.py +8 -189
- classiq/execution/functions/state_vector.py +113 -0
- classiq/execution/functions/util/__init__.py +0 -0
- classiq/execution/functions/util/backend_preferences.py +188 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +66 -0
- classiq/interface/backend/quantum_backend_providers.py +11 -0
- classiq/interface/exceptions.py +0 -4
- classiq/interface/generator/arith/binary_ops.py +24 -0
- classiq/interface/generator/arith/number_utils.py +15 -6
- classiq/interface/generator/compiler_keywords.py +1 -0
- classiq/interface/generator/function_param_list.py +4 -0
- classiq/interface/generator/function_params.py +1 -1
- classiq/interface/generator/functions/classical_type.py +15 -0
- classiq/interface/generator/functions/type_name.py +17 -4
- classiq/interface/generator/transpiler_basis_gates.py +1 -0
- classiq/interface/generator/types/compilation_metadata.py +15 -6
- classiq/interface/hardware.py +1 -0
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/model.py +19 -0
- classiq/interface/model/quantum_type.py +15 -0
- classiq/interface/qubits_mapping/__init__.py +4 -0
- classiq/interface/qubits_mapping/path_expr_range.py +69 -0
- classiq/interface/qubits_mapping/qubits_mapping.py +231 -0
- classiq/interface/qubits_mapping/slices.py +112 -0
- classiq/model_expansions/arithmetic.py +6 -0
- classiq/qmod/builtins/functions/__init__.py +12 -9
- classiq/qmod/builtins/functions/allocation.py +0 -36
- classiq/qmod/builtins/functions/arithmetic.py +52 -0
- classiq/qmod/builtins/functions/gray_code.py +23 -0
- classiq/qmod/builtins/functions/mcx_func.py +10 -0
- classiq/qmod/builtins/structs.py +22 -3
- classiq/qprog_to_cudaq.py +347 -0
- {classiq-0.104.0.dist-info → classiq-1.0.0.dist-info}/METADATA +4 -1
- {classiq-0.104.0.dist-info → classiq-1.0.0.dist-info}/RECORD +52 -39
- /classiq/execution/functions/{_logging.py → util/_logging.py} +0 -0
- /classiq/execution/functions/{constants.py → util/constants.py} +0 -0
- /classiq/execution/functions/{parse_provider_backend.py → util/parse_provider_backend.py} +0 -0
- {classiq-0.104.0.dist-info → classiq-1.0.0.dist-info}/WHEEL +0 -0
- {classiq-0.104.0.dist-info → classiq-1.0.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from collections import deque
|
|
2
|
+
from collections.abc import Iterable, Reversible
|
|
3
|
+
from itertools import chain
|
|
4
|
+
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Slices(deque[tuple[int, int]]):
|
|
9
|
+
"""A deque of slice objects that automatically merges adjacent slices.
|
|
10
|
+
|
|
11
|
+
Slices represent a collection of non-overlapping, potentially non-contiguous
|
|
12
|
+
slice ranges. When slices are appended or prepended, adjacent slices are
|
|
13
|
+
automatically merged to maintain a compact representation. Methods use virtual
|
|
14
|
+
notation, access the elements in the object as if all slices were explicitly
|
|
15
|
+
written out contiguously.
|
|
16
|
+
|
|
17
|
+
The class is primarily used for managing qubit allocations and mappings in
|
|
18
|
+
quantum circuit synthesis, where it tracks which physical qubit ranges
|
|
19
|
+
correspond to logical variable ranges.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
@override
|
|
23
|
+
def append(self, physical_slice: tuple[int, int]) -> None:
|
|
24
|
+
if self and self[-1][1] == physical_slice[0]:
|
|
25
|
+
last_physical_slice = self.pop()
|
|
26
|
+
new_physical_slice = (last_physical_slice[0], physical_slice[1])
|
|
27
|
+
else:
|
|
28
|
+
new_physical_slice = physical_slice
|
|
29
|
+
super().append(new_physical_slice)
|
|
30
|
+
|
|
31
|
+
@override
|
|
32
|
+
def appendleft(self, physical_slice: tuple[int, int]) -> None:
|
|
33
|
+
if self and self[0][0] == physical_slice[1]:
|
|
34
|
+
first_physical_slice = self.popleft()
|
|
35
|
+
new_physical_slice = (physical_slice[0], first_physical_slice[1])
|
|
36
|
+
else:
|
|
37
|
+
new_physical_slice = physical_slice
|
|
38
|
+
super().appendleft(new_physical_slice)
|
|
39
|
+
|
|
40
|
+
def _multiple_appendleft(
|
|
41
|
+
self, physical_slices: Reversible[tuple[int, int]]
|
|
42
|
+
) -> None:
|
|
43
|
+
for physical_slice in reversed(physical_slices):
|
|
44
|
+
self.appendleft(physical_slice)
|
|
45
|
+
|
|
46
|
+
@override
|
|
47
|
+
def extend(self, physical_slices: Iterable[tuple[int, int]]) -> None:
|
|
48
|
+
for physical_slice in physical_slices:
|
|
49
|
+
self.append(physical_slice)
|
|
50
|
+
|
|
51
|
+
def pop_prefix_virtual_slice(self, virtual_end: int) -> "Slices":
|
|
52
|
+
result = Slices()
|
|
53
|
+
current_virtual_end, result_physical_end, physical_slice_end = 0, 0, 0
|
|
54
|
+
while current_virtual_end < virtual_end:
|
|
55
|
+
physical_slice_start, physical_slice_end = self.popleft()
|
|
56
|
+
current_virtual_end += physical_slice_end - physical_slice_start
|
|
57
|
+
overlap_virtual_end = min(virtual_end, current_virtual_end)
|
|
58
|
+
result_physical_end = physical_slice_end + (
|
|
59
|
+
overlap_virtual_end - current_virtual_end
|
|
60
|
+
)
|
|
61
|
+
result.append((physical_slice_start, result_physical_end))
|
|
62
|
+
if result_physical_end != physical_slice_end:
|
|
63
|
+
self.appendleft((result_physical_end, physical_slice_end))
|
|
64
|
+
return result
|
|
65
|
+
|
|
66
|
+
def get_virtual_slice(self, virtual_start: int, virtual_end: int) -> "Slices":
|
|
67
|
+
result = Slices()
|
|
68
|
+
current_virtual_start = 0
|
|
69
|
+
for physical_slice in self:
|
|
70
|
+
physical_slice_start, physical_slice_end = physical_slice
|
|
71
|
+
current_virtual_end = current_virtual_start + (
|
|
72
|
+
physical_slice_end - physical_slice_start
|
|
73
|
+
)
|
|
74
|
+
overlap_virtual_start = max(virtual_start, current_virtual_start)
|
|
75
|
+
overlap_virtual_end = min(virtual_end, current_virtual_end)
|
|
76
|
+
if overlap_virtual_start < overlap_virtual_end:
|
|
77
|
+
new_physical_start = physical_slice_start + (
|
|
78
|
+
overlap_virtual_start - current_virtual_start
|
|
79
|
+
)
|
|
80
|
+
new_physical_end = physical_slice_end + (
|
|
81
|
+
overlap_virtual_end - current_virtual_end
|
|
82
|
+
)
|
|
83
|
+
result.append((new_physical_start, new_physical_end))
|
|
84
|
+
if current_virtual_end >= virtual_end:
|
|
85
|
+
break
|
|
86
|
+
current_virtual_start = current_virtual_end
|
|
87
|
+
return result
|
|
88
|
+
|
|
89
|
+
def update_virtual_slice(
|
|
90
|
+
self, virtual_start: int, virtual_end: int, new: "Slices"
|
|
91
|
+
) -> None:
|
|
92
|
+
start = self.pop_prefix_virtual_slice(virtual_start)
|
|
93
|
+
self.pop_prefix_virtual_slice(virtual_end - virtual_start)
|
|
94
|
+
self._multiple_appendleft(new)
|
|
95
|
+
self._multiple_appendleft(start)
|
|
96
|
+
|
|
97
|
+
def mapping_virtual_slices(self, virtual_slices: "Slices") -> "Slices":
|
|
98
|
+
mappings = Slices()
|
|
99
|
+
for virtual_slice in virtual_slices:
|
|
100
|
+
virtual_start, virtual_end = virtual_slice
|
|
101
|
+
for mapped_slice in self.get_virtual_slice(virtual_start, virtual_end):
|
|
102
|
+
mappings.append(mapped_slice)
|
|
103
|
+
return mappings
|
|
104
|
+
|
|
105
|
+
def size(self) -> int:
|
|
106
|
+
return sum(_slice[1] - _slice[0] for _slice in self)
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def indices(self) -> tuple[int, ...]:
|
|
110
|
+
return tuple(
|
|
111
|
+
chain.from_iterable(range(_slice[0], _slice[1]) for _slice in self)
|
|
112
|
+
)
|
|
@@ -88,6 +88,12 @@ class NumericAttributes:
|
|
|
88
88
|
return self.lb
|
|
89
89
|
return None
|
|
90
90
|
|
|
91
|
+
def fits_in(self, other: "NumericAttributes") -> bool:
|
|
92
|
+
return (
|
|
93
|
+
self.integer_digits <= other.integer_digits
|
|
94
|
+
and self.fraction_digits <= other.fraction_digits
|
|
95
|
+
)
|
|
96
|
+
|
|
91
97
|
@classmethod
|
|
92
98
|
def from_bounds(
|
|
93
99
|
cls,
|
|
@@ -2,7 +2,8 @@ from .allocation import *
|
|
|
2
2
|
from .arithmetic import *
|
|
3
3
|
from .benchmarking import *
|
|
4
4
|
from .exponentiation import *
|
|
5
|
-
from .
|
|
5
|
+
from .gray_code import *
|
|
6
|
+
from .mcx_func import *
|
|
6
7
|
from .mid_circuit_measurement import *
|
|
7
8
|
from .operators import *
|
|
8
9
|
from .standard_gates import *
|
|
@@ -38,12 +39,12 @@ CORE_LIB_DECLS = [
|
|
|
38
39
|
SWAP,
|
|
39
40
|
IDENTITY,
|
|
40
41
|
prepare_state,
|
|
41
|
-
prepare_state_approx,
|
|
42
42
|
prepare_amplitudes,
|
|
43
|
-
prepare_amplitudes_approx,
|
|
44
43
|
unitary,
|
|
45
44
|
add,
|
|
46
45
|
add_inplace_right,
|
|
46
|
+
canonical_add,
|
|
47
|
+
canonical_add_constant,
|
|
47
48
|
modular_add,
|
|
48
49
|
integer_xor,
|
|
49
50
|
modular_add_constant,
|
|
@@ -58,9 +59,7 @@ CORE_LIB_DECLS = [
|
|
|
58
59
|
drop,
|
|
59
60
|
randomized_benchmarking,
|
|
60
61
|
inplace_prepare_state,
|
|
61
|
-
inplace_prepare_state_approx,
|
|
62
62
|
inplace_prepare_amplitudes,
|
|
63
|
-
inplace_prepare_amplitudes_approx,
|
|
64
63
|
single_pauli_exponent,
|
|
65
64
|
commuting_paulis_exponent,
|
|
66
65
|
suzuki_trotter,
|
|
@@ -74,7 +73,10 @@ CORE_LIB_DECLS = [
|
|
|
74
73
|
exponentiation_with_depth_constraint,
|
|
75
74
|
RESET,
|
|
76
75
|
mcx,
|
|
76
|
+
mcx_gray_code,
|
|
77
|
+
mcx_hybrid_rec,
|
|
77
78
|
SX,
|
|
79
|
+
select_rotation,
|
|
78
80
|
)
|
|
79
81
|
]
|
|
80
82
|
|
|
@@ -94,6 +96,8 @@ __all__ = [ # noqa: RUF022
|
|
|
94
96
|
"I",
|
|
95
97
|
"IDENTITY",
|
|
96
98
|
"mcx",
|
|
99
|
+
"mcx_gray_code",
|
|
100
|
+
"mcx_hybrid_rec",
|
|
97
101
|
"PHASE",
|
|
98
102
|
"R",
|
|
99
103
|
"RX",
|
|
@@ -114,6 +118,8 @@ __all__ = [ # noqa: RUF022
|
|
|
114
118
|
"SX",
|
|
115
119
|
"add",
|
|
116
120
|
"add_inplace_right",
|
|
121
|
+
"canonical_add",
|
|
122
|
+
"canonical_add_constant",
|
|
117
123
|
"apply",
|
|
118
124
|
"exponentiation_with_depth_constraint",
|
|
119
125
|
"multiply",
|
|
@@ -123,9 +129,7 @@ __all__ = [ # noqa: RUF022
|
|
|
123
129
|
"free",
|
|
124
130
|
"drop",
|
|
125
131
|
"inplace_prepare_amplitudes",
|
|
126
|
-
"inplace_prepare_amplitudes_approx",
|
|
127
132
|
"inplace_prepare_state",
|
|
128
|
-
"inplace_prepare_state_approx",
|
|
129
133
|
"integer_xor",
|
|
130
134
|
"modular_add",
|
|
131
135
|
"modular_add_constant",
|
|
@@ -133,9 +137,7 @@ __all__ = [ # noqa: RUF022
|
|
|
133
137
|
"parametric_suzuki_trotter",
|
|
134
138
|
"permute",
|
|
135
139
|
"prepare_amplitudes",
|
|
136
|
-
"prepare_amplitudes_approx",
|
|
137
140
|
"prepare_state",
|
|
138
|
-
"prepare_state_approx",
|
|
139
141
|
"qdrift",
|
|
140
142
|
"randomized_benchmarking",
|
|
141
143
|
"real_xor_constant",
|
|
@@ -144,6 +146,7 @@ __all__ = [ # noqa: RUF022
|
|
|
144
146
|
"suzuki_trotter",
|
|
145
147
|
"unitary",
|
|
146
148
|
"RESET",
|
|
149
|
+
"select_rotation",
|
|
147
150
|
]
|
|
148
151
|
BUILTIN_FUNCTION_DECLARATIONS = {
|
|
149
152
|
func_decl.name: func_decl for func_decl in STD_QMOD_OPERATORS + CORE_LIB_DECLS
|
|
@@ -144,39 +144,3 @@ def inplace_prepare_amplitudes(
|
|
|
144
144
|
|
|
145
145
|
"""
|
|
146
146
|
pass
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
@qfunc(external=True)
|
|
150
|
-
def inplace_prepare_amplitudes_approx(
|
|
151
|
-
amplitudes: CArray[CReal],
|
|
152
|
-
bound: CReal,
|
|
153
|
-
target: QArray[QBit, Literal["log(amplitudes.len, 2)"]],
|
|
154
|
-
) -> None:
|
|
155
|
-
pass
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
@qfunc(external=True)
|
|
159
|
-
def prepare_amplitudes_approx(
|
|
160
|
-
amplitudes: CArray[CReal],
|
|
161
|
-
bound: CReal,
|
|
162
|
-
out: Output[QArray[QBit, Literal["log(amplitudes.len, 2)"]]],
|
|
163
|
-
) -> None:
|
|
164
|
-
pass
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
@qfunc(external=True)
|
|
168
|
-
def inplace_prepare_state_approx(
|
|
169
|
-
probabilities: CArray[CReal],
|
|
170
|
-
bound: CReal,
|
|
171
|
-
target: QArray[QBit, Literal["log(probabilities.len, 2)"]],
|
|
172
|
-
) -> None:
|
|
173
|
-
pass
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
@qfunc(external=True)
|
|
177
|
-
def prepare_state_approx(
|
|
178
|
-
probabilities: CArray[CReal],
|
|
179
|
-
bound: CReal,
|
|
180
|
-
out: Output[QArray[QBit, Literal["log(probabilities.len, 2)"]]],
|
|
181
|
-
) -> None:
|
|
182
|
-
pass
|
|
@@ -66,6 +66,58 @@ def add_inplace_right(
|
|
|
66
66
|
pass
|
|
67
67
|
|
|
68
68
|
|
|
69
|
+
@qperm(external=True)
|
|
70
|
+
def canonical_add(
|
|
71
|
+
left: Const[QArray],
|
|
72
|
+
extend_left: CBool,
|
|
73
|
+
right: QArray,
|
|
74
|
+
) -> None:
|
|
75
|
+
"""
|
|
76
|
+
[Qmod core-library function]
|
|
77
|
+
|
|
78
|
+
Adds two quantum variables representing integers (signed or unsigned), storing the
|
|
79
|
+
result in the second variable (in-place):
|
|
80
|
+
|
|
81
|
+
$$
|
|
82
|
+
\\left|\\text{left}\\right\\rangle \\left|\\text{right}\\right\\rangle
|
|
83
|
+
\\mapsto
|
|
84
|
+
\\left|\\text{left}\\right\\rangle \\left|\\left(\\text{right} +
|
|
85
|
+
\\text{left}\\right) \\bmod 2^{\\text{right.size}} \\right\\rangle
|
|
86
|
+
$$
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
left: The out-of-place argument for the addition.
|
|
90
|
+
extend_left: Whether to sign-extend the left argument.
|
|
91
|
+
right: The in-place argument for the addition, holds the final result.
|
|
92
|
+
"""
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@qperm(external=True)
|
|
97
|
+
def canonical_add_constant(
|
|
98
|
+
left: CInt,
|
|
99
|
+
right: QArray,
|
|
100
|
+
) -> None:
|
|
101
|
+
"""
|
|
102
|
+
[Qmod core-library function]
|
|
103
|
+
|
|
104
|
+
Adds an integer constant to a quantum variable representing an integer (signed or
|
|
105
|
+
unsigned):
|
|
106
|
+
|
|
107
|
+
$$
|
|
108
|
+
\\left|\\text{right}\\right\\rangle
|
|
109
|
+
\\mapsto
|
|
110
|
+
\\left|\\left(\\text{right} +
|
|
111
|
+
\\text{left}\\right) \\bmod 2^{\\text{right.size}} \\right\\rangle
|
|
112
|
+
$$
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
left: The constant argument for the addition.
|
|
116
|
+
right: The quantum argument for the addition, holds the final result.
|
|
117
|
+
"""
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
|
|
69
121
|
@qperm(external=True)
|
|
70
122
|
def modular_add(left: Const[QArray[QBit]], right: QArray[QBit]) -> None:
|
|
71
123
|
pass
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from classiq.qmod.builtins.enums import Pauli
|
|
2
|
+
from classiq.qmod.qfunc import qfunc
|
|
3
|
+
from classiq.qmod.qmod_parameter import CArray, CReal
|
|
4
|
+
from classiq.qmod.qmod_variable import QBit, QNum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@qfunc(external=True)
|
|
8
|
+
def select_rotation(
|
|
9
|
+
basis: Pauli, angles: CArray[CReal], selector: QNum, target: QBit
|
|
10
|
+
) -> None:
|
|
11
|
+
"""
|
|
12
|
+
[Qmod core-library function]
|
|
13
|
+
|
|
14
|
+
Applies a set of controlled single-qubit rotations to a target qubit, using
|
|
15
|
+
a specified rotation axis and a list of rotation angles.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
basis: The Pauli operator defining the rotation axis.
|
|
19
|
+
angles: The list of rotation angles in radians. The list must have length 2**selector.size.
|
|
20
|
+
selector: The qubits that act as the selection register.
|
|
21
|
+
target: The qubit on which the selected rotation is applied.
|
|
22
|
+
"""
|
|
23
|
+
pass
|
|
@@ -5,3 +5,13 @@ from classiq.qmod.qmod_variable import Const, QArray, QBit
|
|
|
5
5
|
@qperm(external=True)
|
|
6
6
|
def mcx(ctrl: Const[QArray[QBit]], target: QBit) -> None:
|
|
7
7
|
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@qperm(external=True)
|
|
11
|
+
def mcx_gray_code(ctrl: Const[QArray[QBit]], target: QBit) -> None:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@qperm(external=True)
|
|
16
|
+
def mcx_hybrid_rec(ctrl: Const[QArray[QBit]], target: QBit, aux: QArray[QBit]) -> None:
|
|
17
|
+
pass
|
classiq/qmod/builtins/structs.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass, fields, is_dataclass
|
|
2
|
-
from typing import Union
|
|
2
|
+
from typing import Any, Union
|
|
3
3
|
|
|
4
4
|
from classiq.interface.exceptions import ClassiqValueError
|
|
5
5
|
from classiq.interface.generator.types.struct_declaration import StructDeclaration
|
|
@@ -117,13 +117,21 @@ class SparsePauliOp:
|
|
|
117
117
|
def __rmul__(self, obj: Union[float, "SparsePauliOp"]) -> "SparsePauliOp":
|
|
118
118
|
return self.__mul__(obj)
|
|
119
119
|
|
|
120
|
-
def __add__(self, other:
|
|
120
|
+
def __add__(self, other: Any) -> "SparsePauliOp":
|
|
121
|
+
if not isinstance(other, SparsePauliOp):
|
|
122
|
+
raise ClassiqValueError(
|
|
123
|
+
f"Cannot add an object of type {type(other).__name__} to SparsePauliOp"
|
|
124
|
+
)
|
|
121
125
|
return SparsePauliOp(
|
|
122
126
|
terms=LenList(self.terms + other.terms),
|
|
123
127
|
num_qubits=max(self.num_qubits, other.num_qubits),
|
|
124
128
|
)
|
|
125
129
|
|
|
126
|
-
def __sub__(self, other:
|
|
130
|
+
def __sub__(self, other: Any) -> "SparsePauliOp":
|
|
131
|
+
if not isinstance(other, SparsePauliOp):
|
|
132
|
+
raise ClassiqValueError(
|
|
133
|
+
f"Cannot substruct an object of type {type(other).__name__} to SparsePauliOp"
|
|
134
|
+
)
|
|
127
135
|
return self + -1.0 * other
|
|
128
136
|
|
|
129
137
|
def __str__(self) -> str:
|
|
@@ -136,6 +144,17 @@ class SparsePauliOp:
|
|
|
136
144
|
for term in self.terms
|
|
137
145
|
)
|
|
138
146
|
|
|
147
|
+
def __truediv__(self, other: Any) -> "SparsePauliOp":
|
|
148
|
+
if not isinstance(other, (int, float)):
|
|
149
|
+
raise ClassiqValueError(
|
|
150
|
+
f"Cannot divide SparsePauliOp by object of type {type(other).__name__}"
|
|
151
|
+
)
|
|
152
|
+
if other == 0:
|
|
153
|
+
raise ClassiqValueError("Cannot divide by zero")
|
|
154
|
+
return SparsePauliOp(terms=self.terms, num_qubits=self.num_qubits) * float(
|
|
155
|
+
1 / other
|
|
156
|
+
)
|
|
157
|
+
|
|
139
158
|
|
|
140
159
|
@dataclass
|
|
141
160
|
class CombinatorialOptimizationSolution:
|