Skip to content

Commit

Permalink
Merge branch 'main' into mstechly/qref-integration
Browse files Browse the repository at this point in the history
  • Loading branch information
mstechly authored Aug 13, 2024
2 parents bad1366 + 4159901 commit 6186e9e
Show file tree
Hide file tree
Showing 11 changed files with 231 additions and 93 deletions.
8 changes: 3 additions & 5 deletions qualtran/_infra/adjoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

from functools import cached_property
from typing import cast, Dict, List, Optional, Set, Tuple, TYPE_CHECKING
from typing import Dict, List, Optional, Set, Tuple, TYPE_CHECKING

import cirq
from attrs import frozen
Expand All @@ -24,7 +24,7 @@
from .registers import Signature

if TYPE_CHECKING:
from qualtran import Bloq, CompositeBloq, Register, Signature, Soquet, SoquetT
from qualtran import Bloq, CompositeBloq, Register, Signature, SoquetT
from qualtran.drawing import WireSymbol
from qualtran.resource_counting import BloqCountT, SympySymbolAllocator

Expand Down Expand Up @@ -176,10 +176,8 @@ def wire_symbol(
# Note: since we pass are passed a soquet which has the 'new' side, we flip it before
# delegating and then flip back. Subbloqs only have to answer this protocol
# if the provided soquet is facing the correct direction.
from qualtran.drawing import Text

if reg is None:
return Text(cast(Text, self.subbloq.wire_symbol(reg=None)).text + '†')
return self.subbloq.wire_symbol(reg=None).adjoint()

return self.subbloq.wire_symbol(reg=reg.adjoint(), idx=idx).adjoint()

Expand Down
12 changes: 7 additions & 5 deletions qualtran/_infra/composite_bloq.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,20 +1200,22 @@ def _fin(idxed_soq: Soquet, reg: Register, idx: Tuple[int, ...]):
connections=self._cxns, signature=signature, bloq_instances=self._binsts
)

def allocate(self, n: Union[int, sympy.Expr] = 1, dtype: Optional[QDType] = None) -> Soquet:
def allocate(
self, n: Union[int, sympy.Expr] = 1, dtype: Optional[QDType] = None, dirty: bool = False
) -> Soquet:
from qualtran.bloqs.bookkeeping import Allocate

if dtype is not None:
return self.add(Allocate(dtype=dtype))
return self.add(Allocate(dtype=(QAny(n))))
return self.add(Allocate(dtype=dtype, dirty=dirty))
return self.add(Allocate(dtype=(QAny(n)), dirty=dirty))

def free(self, soq: Soquet) -> None:
def free(self, soq: Soquet, dirty: bool = False) -> None:
from qualtran.bloqs.bookkeeping import Free

if not isinstance(soq, Soquet):
raise ValueError("`free` expects a single Soquet to free.")

self.add(Free(dtype=soq.reg.dtype), reg=soq)
self.add(Free(dtype=soq.reg.dtype, dirty=dirty), reg=soq)

def split(self, soq: Soquet) -> NDArray[Soquet]: # type: ignore[type-var]
"""Add a Split bloq to split up a register."""
Expand Down
12 changes: 8 additions & 4 deletions qualtran/bloqs/bookkeeping/allocate.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ class Allocate(_BookkeepingBloq):
Args:
dtype: the quantum data type of the allocated register.
dirty: If true, represents a borrowing operation where allocated qubits can be dirty.
Registers:
reg [right]: The allocated register.
"""

dtype: QDType
dirty: bool = False

@cached_property
def signature(self) -> Signature:
Expand All @@ -64,7 +66,7 @@ def decompose_bloq(self) -> 'CompositeBloq':
def adjoint(self) -> 'Bloq':
from qualtran.bloqs.bookkeeping.free import Free

return Free(self.dtype)
return Free(self.dtype, self.dirty)

def on_classical_vals(self) -> Dict[str, int]:
return {'reg': 0}
Expand All @@ -91,10 +93,12 @@ def as_cirq_op(
self, qubit_manager: 'cirq.QubitManager'
) -> Tuple[Union['cirq.Operation', None], Dict[str, 'CirqQuregT']]:
shape = (*self.signature[0].shape, self.signature[0].bitsize)
return (
None,
{'reg': np.array(qubit_manager.qalloc(self.signature.n_qubits())).reshape(shape)},
qubits = (
qubit_manager.qborrow(self.signature.n_qubits())
if self.dirty
else qubit_manager.qalloc(self.signature.n_qubits())
)
return (None, {'reg': np.array(qubits).reshape(shape)})


@bloq_example
Expand Down
6 changes: 4 additions & 2 deletions qualtran/bloqs/bookkeeping/bookkeeping.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"Allocate an `n` bit register.\n",
"\n",
"#### Parameters\n",
" - `dtype`: the quantum data type of the allocated register. \n",
" - `dtype`: the quantum data type of the allocated register.\n",
" - `dirty`: If true, represents a borrowing operation where allocated qubits can be dirty. \n",
"\n",
"#### Registers\n",
" - `reg [right]`: The allocated register.\n"
Expand Down Expand Up @@ -146,7 +147,8 @@
"vector after freeing qubits and make sure it is normalized.\n",
"\n",
"#### Parameters\n",
" - `dtype`: The quantum data type of the register to be freed. \n",
" - `dtype`: The quantum data type of the register to be freed.\n",
" - `dirty`: If true, represents adjoint of a borrowing operation where deallocated qubits were borrowed dirty from another part of the algorithm and must be free'd in the same dirty state. \n",
"\n",
"#### Registers\n",
" - `reg [left]`: The register to free.\n"
Expand Down
10 changes: 7 additions & 3 deletions qualtran/bloqs/bookkeeping/free.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,16 @@ class Free(_BookkeepingBloq):
Args:
dtype: The quantum data type of the register to be freed.
dirty: If true, represents adjoint of a borrowing operation where deallocated qubits
were borrowed dirty from another part of the algorithm and must be free'd in the same
dirty state.
Registers:
reg [left]: The register to free.
"""

dtype: QDType
dirty: bool = False

@cached_property
def signature(self) -> Signature:
Expand All @@ -69,11 +73,11 @@ def decompose_bloq(self) -> 'CompositeBloq':
def adjoint(self) -> 'Bloq':
from qualtran.bloqs.bookkeeping.allocate import Allocate

return Allocate(self.dtype)
return Allocate(self.dtype, self.dirty)

def on_classical_vals(self, reg: int) -> Dict[str, 'ClassicalValT']:
if reg != 0:
raise ValueError(f"Tried to free a non-zero register: {reg}.")
if reg != 0 and not self.dirty:
raise ValueError(f"Tried to free a non-zero register: {reg} with {self.dirty=}")
return {}

def my_tensors(
Expand Down
3 changes: 3 additions & 0 deletions qualtran/bloqs/data_loading/qrom.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']:
n_cnot = prod(self.target_bitsizes) * prod(self.data_shape)
return {(And(), n_and), (And().adjoint(), n_and), (CNOT(), n_cnot)}

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


@bloq_example
def _qrom_small() -> QROM:
Expand Down
Loading

0 comments on commit 6186e9e

Please sign in to comment.