Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GQSP] Reorganize code into module qsp #848

Merged
merged 12 commits into from
Apr 9, 2024
6 changes: 6 additions & 0 deletions dev_tools/autogenerate-bloqs-notebooks-v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
import qualtran.bloqs.phase_estimation.lp_resource_state
import qualtran.bloqs.qft.approximate_qft
import qualtran.bloqs.qft.two_bit_ffft
import qualtran.bloqs.qsp.generalized_qsp
import qualtran.bloqs.qubitization_walk_operator
import qualtran.bloqs.reflection
import qualtran.bloqs.rotations.phasing_via_cost_function
Expand Down Expand Up @@ -476,6 +477,11 @@
],
directory=f'{SOURCE_DIR}/bloqs/state_preparation/',
),
NotebookSpecV2(
title='Generalized Quantum Signal Processing',
module=qualtran.bloqs.qsp.generalized_qsp,
bloq_specs=[qualtran.bloqs.qsp.generalized_qsp._Generalized_QSP_DOC],
),
]

# --------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions docs/bloqs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,4 @@ Bloqs Library
multiplexers/select_pauli_lcu.ipynb
state_preparation/state_preparation_alias_sampling.ipynb
state_preparation/state_preparation_via_rotation.ipynb
qsp/generalized_qsp.ipynb
64 changes: 63 additions & 1 deletion qualtran/bloqs/for_testing/atom.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import numpy as np
from attrs import frozen

from qualtran import Bloq, CompositeBloq, DecomposeTypeError, Signature, SoquetT
from qualtran import Bloq, CompositeBloq, DecomposeTypeError, GateWithRegisters, Signature, SoquetT
from qualtran.cirq_interop.t_complexity_protocol import TComplexity

if TYPE_CHECKING:
Expand Down Expand Up @@ -111,3 +111,65 @@ def add_my_tensors(

def short_name(self) -> str:
return 'op'


@frozen(repr=False)
class TestGWRAtom(GateWithRegisters):
"""An atomic gate that derives from `GateWithRegisters` useful for testing.

The single qubit gate has a unitary effect corresponding to a 2x2 identity matrix.

Args:
tag: An optional string for differentiating `TestGWRAtom`s.

Registers:
q: One bit
"""

tag: Optional[str] = None

@cached_property
def signature(self) -> Signature:
return Signature.build(q=1)

def decompose_bloq(self) -> 'CompositeBloq':
raise DecomposeTypeError(f"{self} is atomic")

def add_my_tensors(
self,
tn: 'qtn.TensorNetwork',
tag: Any,
*,
incoming: Dict[str, 'SoquetT'],
outgoing: Dict[str, 'SoquetT'],
):
import quimb.tensor as qtn

tn.add(
qtn.Tensor(
data=self._unitary_(),
inds=(outgoing['q'], incoming['q']),
tags=[self.short_name(), tag],
)
)

def _unitary_(self):
return np.eye(2)

def adjoint(self) -> 'Bloq':
return self

def _t_complexity_(self) -> 'TComplexity':
return TComplexity(100)

def __repr__(self):
if self.tag:
return f'TestGWRAtom({self.tag!r})'
else:
return 'TestGWRAtom()'

def short_name(self) -> str:
if self.tag:
return self.tag
else:
return 'GWRAtom'
12 changes: 11 additions & 1 deletion qualtran/bloqs/for_testing/atom_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import cirq
import numpy as np
import pytest

from qualtran import DecomposeTypeError
from qualtran.bloqs.for_testing.atom import TestAtom, TestTwoBitOp
from qualtran.bloqs.for_testing.atom import TestAtom, TestGWRAtom, TestTwoBitOp


def test_test_atom():
Expand All @@ -31,3 +32,12 @@ def test_test_two_bit_op():
np.testing.assert_allclose(
tba.tensor_contract(), np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
)


def test_test_gwr_atom():
ta = TestGWRAtom()
assert ta.short_name() == 'GWRAtom'
with pytest.raises(DecomposeTypeError):
ta.decompose_bloq()
assert ta.adjoint() == ta
np.testing.assert_allclose(cirq.unitary(ta), np.eye(2))
48 changes: 48 additions & 0 deletions qualtran/bloqs/for_testing/random_gate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Tuple

import numpy as np
from attrs import field, frozen
from cirq.testing import random_unitary

from qualtran import GateWithRegisters, Signature


@frozen
class RandomGate(GateWithRegisters):
bitsize: int
matrix: Tuple[Tuple[complex, ...], ...] = field(
converter=lambda mat: tuple(tuple(row) for row in mat)
)

@staticmethod
def create(bitsize: int, *, random_state=None) -> 'RandomGate':
matrix = random_unitary(2**bitsize, random_state=random_state)
return RandomGate(bitsize, matrix)

@property
def signature(self) -> Signature:
return Signature.build(q=self.bitsize)

def _unitary_(self):
return np.array(self.matrix)

def adjoint(self) -> 'RandomGate':
return RandomGate(self.bitsize, np.conj(self.matrix).T)

def __pow__(self, power):
if power == -1:
return self.adjoint()
return NotImplemented
27 changes: 27 additions & 0 deletions qualtran/bloqs/for_testing/random_gate_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import cirq
import numpy as np
import pytest

from .random_gate import RandomGate


@pytest.mark.parametrize("bitsize", [1, 2, 3])
def test_create_and_unitary(bitsize: int):
random_state = np.random.RandomState(42)
for _ in range(5):
gate = RandomGate.create(bitsize, random_state=random_state)
np.testing.assert_allclose(cirq.unitary(gate), gate.matrix)
np.testing.assert_allclose(cirq.unitary(gate**-1), np.conj(gate.matrix).T)
125 changes: 0 additions & 125 deletions qualtran/bloqs/generalized_qsp.ipynb

This file was deleted.

13 changes: 13 additions & 0 deletions qualtran/bloqs/qsp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Loading
Loading