Skip to content

Commit

Permalink
Let ruff do its thing
Browse files Browse the repository at this point in the history
  • Loading branch information
stand-by committed Jul 15, 2024
1 parent 07e01af commit 1c1351e
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 75 deletions.
50 changes: 24 additions & 26 deletions benchmarks/pauli_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@


def pauli_matrices() -> dict:
s0 = np.array([[1,0],[0,1]], dtype=np.complex128)
s1 = np.array([[0,1],[1,0]], dtype=np.complex128)
s2 = np.array([[0,-1j],[1j,0]], dtype=np.complex128)
s3 = np.array([[1,0],[0,-1]], dtype=np.complex128)
return {'I': s0, 'X': s1, 'Y': s2, 'Z': s3, 0: s0, 1: s1, 2: s2, 3: s3}
s0 = np.array([[1, 0], [0, 1]], dtype=np.complex128)
s1 = np.array([[0, 1], [1, 0]], dtype=np.complex128)
s2 = np.array([[0, -1j], [1j, 0]], dtype=np.complex128)
s3 = np.array([[1, 0], [0, -1]], dtype=np.complex128)
return {"I": s0, "X": s1, "Y": s2, "Z": s3, 0: s0, 1: s1, 2: s2, 3: s3}


@dataclass
Expand Down Expand Up @@ -58,7 +58,6 @@ def __init__(self, pauli: PauliString) -> None:
self.n_vals = 1 << self.n_qubits
self.n_ys = pauli.string.count("Y")


def __resolve_init_conditions(self) -> None:
first_col = 0
for p in self.pauli.string:
Expand All @@ -75,20 +74,19 @@ def __resolve_init_conditions(self) -> None:
first_val = -1.0
case 3:
first_val = 1.0j

return first_col, first_val

return first_col, first_val

def sparse_pauli(self) -> SparsePauliString:
cols = np.empty(self.n_vals, dtype=np.int32)
vals = np.empty(self.n_vals, dtype=np.complex128)
cols[0], vals[0] = self.__resolve_init_conditions()

for l in range(self.n_qubits):
p = self.pauli.string[self.n_qubits - l - 1]
pow_of_two = 1 << l
new_slice = slice(pow_of_two, 2*pow_of_two)
for q in range(self.n_qubits):
p = self.pauli.string[self.n_qubits - q - 1]
pow_of_two = 1 << q

new_slice = slice(pow_of_two, 2 * pow_of_two)
old_slice = slice(0, pow_of_two)

match p:
Expand All @@ -107,18 +105,17 @@ def sparse_pauli(self) -> SparsePauliString:

return SparsePauliString(weight=self.pauli.weight, columns=cols, values=vals)


def sparse_diag_pauli(self) -> SparsePauliString:
assert self.pauli.string.count("X") + self.pauli.string.count("Y") == 0

cols = np.arange(self.n_vals, dtype=np.int32)
vals = np.ones(self.n_vals, dtype=np.complex128)

for l in range(self.n_qubits):
p = self.pauli.string[self.n_qubits - l - 1]
pow_of_two = 1 << l
new_slice = slice(pow_of_two, 2*pow_of_two)
for q in range(self.n_qubits):
p = self.pauli.string[self.n_qubits - q - 1]
pow_of_two = 1 << q

new_slice = slice(pow_of_two, 2 * pow_of_two)
old_slice = slice(0, pow_of_two)

match p:
Expand All @@ -129,7 +126,6 @@ def sparse_diag_pauli(self) -> SparsePauliString:

return SparsePauliString(weight=self.pauli.weight, columns=cols, values=vals)


def efficient_sparse_multiply(self, state: np.ndarray) -> np.ndarray:
assert state.ndim == 2

Expand All @@ -140,11 +136,11 @@ def efficient_sparse_multiply(self, state: np.ndarray) -> np.ndarray:
product = np.empty((self.n_vals, state.shape[1]), dtype=np.complex128)
product[0] = self.pauli.weight * vals[0] * state[cols[0]]

for l in range(self.n_qubits):
p = self.pauli.string[self.n_qubits - l - 1]
pow_of_two = 1 << l
new_slice = slice(pow_of_two, 2*pow_of_two)
for q in range(self.n_qubits):
p = self.pauli.string[self.n_qubits - q - 1]
pow_of_two = 1 << q

new_slice = slice(pow_of_two, 2 * pow_of_two)
old_slice = slice(0, pow_of_two)

match p:
Expand All @@ -161,6 +157,8 @@ def efficient_sparse_multiply(self, state: np.ndarray) -> np.ndarray:
cols[new_slice] = cols[old_slice] + pow_of_two
vals[new_slice] = -vals[old_slice]

product[new_slice] = self.pauli.weight * vals[new_slice, np.newaxis] * state[cols[new_slice]]
product[new_slice] = (
self.pauli.weight * vals[new_slice, np.newaxis] * state[cols[new_slice]]
)

return product
85 changes: 36 additions & 49 deletions benchmarks/test_pauli_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,23 @@ def paulis():

def test_pauli_strings(paulis):
for p in "IXYZ":
np.testing.assert_array_equal(
PauliString(p).dense(), paulis[p]
)
np.testing.assert_array_equal(PauliString(p).dense(), paulis[p])

ps = PauliString("III", 0.5)
np.testing.assert_array_equal(
ps.dense(), np.eye(8) * 0.5
)
np.testing.assert_array_equal(ps.dense(), np.eye(8) * 0.5)

ps = PauliString(weight=1.0, string="IZ")
np.testing.assert_array_equal(
ps.dense(),
np.kron(paulis["I"], paulis["Z"])
)
np.testing.assert_array_equal(ps.dense(), np.kron(paulis["I"], paulis["Z"]))

ps = PauliString(weight=0.5, string="XYZ")
np.testing.assert_array_equal(
ps.dense(),
np.kron(paulis["X"], np.kron(paulis["Y"], paulis["Z"])) * 0.5
ps.dense(), np.kron(paulis["X"], np.kron(paulis["Y"], paulis["Z"])) * 0.5
)

ps = SparsePauliString(np.arange(8), np.ones(8), 0.5)
np.testing.assert_array_equal(
ps.dense(), np.eye(8) * 0.5
)
m = np.array([[0, 1, 0],
[0, 0, 2],
[3, 0, 0]])
ps = SparsePauliString(columns=np.array([1, 2, 0]),
values=np.array([1, 2, 3]))
np.testing.assert_array_equal(ps.dense(), np.eye(8) * 0.5)
m = np.array([[0, 1, 0], [0, 0, 2], [3, 0, 0]])
ps = SparsePauliString(columns=np.array([1, 2, 0]), values=np.array([1, 2, 3]))
np.testing.assert_array_equal(ps.dense(), m)


Expand Down Expand Up @@ -76,15 +63,13 @@ def test_pauli_composer(paulis):
pc = PauliComposer(PauliString("IY"))
np.testing.assert_array_equal(
pc.sparse_pauli().dense(),
np.block([[paulis['Y'], np.zeros((2,2))],
[np.zeros((2,2)), paulis['Y']]])
np.block([[paulis["Y"], np.zeros((2, 2))], [np.zeros((2, 2)), paulis["Y"]]]),
)

pc = PauliComposer(PauliString("IZ"))
np.testing.assert_array_equal(
pc.sparse_pauli().dense(),
np.block([[paulis['Z'], np.zeros((2,2))],
[np.zeros((2,2)), paulis['Z']]])
np.block([[paulis["Z"], np.zeros((2, 2))], [np.zeros((2, 2)), paulis["Z"]]]),
)


Expand All @@ -95,23 +80,23 @@ def test_pauli_composer_equivalence():
w = rng.random()
np.testing.assert_array_equal(
PauliComposer(PauliString(c, w)).sparse_pauli().dense(),
PauliString(c, w).dense()
PauliString(c, w).dense(),
)

for s in permutations("XYZ", 2):
s = ''.join(s)
s = "".join(s)
w = rng.random()
np.testing.assert_array_equal(
PauliComposer(PauliString(s, w)).sparse_pauli().dense(),
PauliString(s, w).dense()
PauliString(s, w).dense(),
)

for s in permutations("IXYZ", 3):
s = ''.join(s)
s = "".join(s)
w = rng.random()
np.testing.assert_array_equal(
PauliComposer(PauliString(s, w)).sparse_pauli().dense(),
PauliString(s, w).dense()
PauliString(s, w).dense(),
)

ixyz = PauliComposer(PauliString("IXYZ")).sparse_pauli().dense()
Expand All @@ -124,55 +109,57 @@ def test_pauli_composer_equivalence():

for s in ["XYIZXYZ", "XXIYYIZZ", "ZIXIZYXX"]:
np.testing.assert_array_equal(
PauliComposer(PauliString(s)).sparse_pauli().dense(),
PauliString(s).dense()
PauliComposer(PauliString(s)).sparse_pauli().dense(), PauliString(s).dense()
)


def test_sparse_pauli_multiply():
rng = np.random.default_rng(321)

for s in chain(list("IXYZ"), list(permutations("IXYZ", 3)),
["XYIZXYZ", "XXIYYIZZ", "ZIXIZYXX"]):
s = ''.join(s)
n = 2**len(s)

for s in chain(
list("IXYZ"), list(permutations("IXYZ", 3)), ["XYIZXYZ", "XXIYYIZZ", "ZIXIZYXX"]
):
s = "".join(s)
n = 2 ** len(s)
w = rng.random()
psi = rng.random(n)
psi_batch = rng.random((n, 25))

np.testing.assert_allclose(
PauliComposer(PauliString(s, w)).sparse_pauli().multiply(psi),
PauliString(s, w).dense().dot(psi),
atol=1e-15
atol=1e-15,
)
np.testing.assert_allclose(
PauliComposer(PauliString(s, w)).sparse_pauli().multiply(psi_batch),
PauliString(s, w).dense() @ psi_batch,
atol=1e-15
atol=1e-15,
)


def test_pauli_composer_multiply():
rng = np.random.default_rng(321)

for s in chain(list("IXYZ"), list(permutations("IXYZ", 3)),
["XYIZXYZ", "XXIYYIZZ", "ZIXIZYXX"]):
s = ''.join(s)
n = 2**len(s)

for s in chain(
list("IXYZ"), list(permutations("IXYZ", 3)), ["XYIZXYZ", "XXIYYIZZ", "ZIXIZYXX"]
):
s = "".join(s)
n = 2 ** len(s)
w = rng.random()
psi = rng.random(n)
psi_batch = rng.random((n, 20))

np.testing.assert_allclose(
PauliComposer(PauliString(s, w)).efficient_sparse_multiply(
psi.reshape(-1, 1)).ravel(),
PauliComposer(PauliString(s, w))
.efficient_sparse_multiply(psi.reshape(-1, 1))
.ravel(),
PauliString(s, w).dense().dot(psi),
atol=1e-15
atol=1e-15,
)
np.testing.assert_allclose(
PauliComposer(PauliString(s, w)).efficient_sparse_multiply(psi_batch),
PauliString(s, w).dense() @ psi_batch,
atol=1e-15
atol=1e-15,
)


Expand Down

0 comments on commit 1c1351e

Please sign in to comment.