Skip to content

Commit

Permalink
Merge branch 'main' into mod_inv
Browse files Browse the repository at this point in the history
  • Loading branch information
NoureldinYosri authored Oct 29, 2024
2 parents cbf1f0c + 7c6715b commit a83d49d
Show file tree
Hide file tree
Showing 12 changed files with 650 additions and 23 deletions.
16 changes: 16 additions & 0 deletions qualtran/_infra/controlled.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
Sequence,
Tuple,
TYPE_CHECKING,
TypeAlias,
Union,
)

Expand All @@ -45,6 +46,9 @@
from qualtran.resource_counting import BloqCountDictT, SympySymbolAllocator
from qualtran.simulation.classical_sim import ClassicalValT

ControlBit: TypeAlias = int
"""A control bit, either 0 or 1."""


def _cvs_convert(
cvs: Union[
Expand Down Expand Up @@ -250,6 +254,18 @@ def from_cirq_cv(
bloq_cvs.append(curr_cvs)
return CtrlSpec(tuple(qdtypes), tuple(bloq_cvs))

def get_single_ctrl_bit(self) -> ControlBit:
"""If controlled by a single qubit, return the control bit, otherwise raise"""
if self.num_qubits != 1:
raise ValueError(f"expected a single qubit control, got {self.num_qubits}")

(qdtype,) = self.qdtypes
(cv,) = self.cvs
(idx,) = Register('', qdtype, cv.shape).all_idxs()
(control_bit,) = qdtype.to_bits(cv[idx])

return int(control_bit)


class AddControlledT(Protocol):
"""The signature for the `add_controlled` callback part of `ctrl_system`.
Expand Down
20 changes: 20 additions & 0 deletions qualtran/_infra/controlled_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,26 @@ def test_ctrl_spec_to_cirq_cv_roundtrip():
assert CtrlSpec.from_cirq_cv(cirq_cv, qdtypes=ctrl_spec.qdtypes, shapes=ctrl_spec.shapes)


@pytest.mark.parametrize(
"ctrl_spec", [CtrlSpec(), CtrlSpec(cvs=[1]), CtrlSpec(cvs=np.atleast_2d([1]))]
)
def test_ctrl_spec_single_bit_one(ctrl_spec: CtrlSpec):
assert ctrl_spec.get_single_ctrl_bit() == 1


@pytest.mark.parametrize(
"ctrl_spec", [CtrlSpec(cvs=0), CtrlSpec(cvs=[0]), CtrlSpec(cvs=np.atleast_2d([0]))]
)
def test_ctrl_spec_single_bit_zero(ctrl_spec: CtrlSpec):
assert ctrl_spec.get_single_ctrl_bit() == 0


@pytest.mark.parametrize("ctrl_spec", [CtrlSpec(cvs=[1, 1]), CtrlSpec(qdtypes=QUInt(2), cvs=0)])
def test_ctrl_spec_single_bit_raises(ctrl_spec: CtrlSpec):
with pytest.raises(ValueError):
ctrl_spec.get_single_ctrl_bit()


def _test_cirq_equivalence(bloq: Bloq, gate: 'cirq.Gate'):
import cirq

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,27 @@
import numpy as np
from numpy.typing import NDArray

from qualtran import bloq_example, BloqDocSpec, BQUInt, QAny, QBit, Register, Signature
from qualtran import (
AddControlledT,
Bloq,
bloq_example,
BloqDocSpec,
BQUInt,
CtrlSpec,
QAny,
QBit,
Register,
Signature,
)
from qualtran._infra.gate_with_registers import total_bits
from qualtran._infra.single_qubit_controlled import SpecializedSingleQubitControlledExtension
from qualtran.bloqs.basic_gates import CSwap
from qualtran.bloqs.multiplexers.apply_gate_to_lth_target import ApplyGateToLthQubit
from qualtran.bloqs.multiplexers.select_base import SelectOracle
from qualtran.bloqs.multiplexers.selected_majorana_fermion import SelectedMajoranaFermion


@attrs.frozen
class SelectHubbard(SelectOracle, SpecializedSingleQubitControlledExtension): # type: ignore[misc]
class SelectHubbard(SelectOracle):
r"""The SELECT operation optimized for the 2D Hubbard model.
In contrast to SELECT for an arbitrary chemistry Hamiltonian, we:
Expand Down Expand Up @@ -180,6 +190,19 @@ def __str__(self):
return f'C{s}'
return s

def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> Tuple['Bloq', 'AddControlledT']:
from qualtran.bloqs.mcmt.specialized_ctrl import get_ctrl_system_1bit_cv

return get_ctrl_system_1bit_cv(
self,
ctrl_spec=ctrl_spec,
current_ctrl_bit=self.control_val,
get_ctrl_bloq_and_ctrl_reg_name=lambda cv: (
attrs.evolve(self, control_val=cv),
'control',
),
)


@bloq_example
def _sel_hubb() -> SelectHubbard:
Expand Down
31 changes: 28 additions & 3 deletions qualtran/bloqs/chemistry/sparse/select_bloq.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,23 @@
from functools import cached_property
from typing import Dict, Optional, Tuple, TYPE_CHECKING

import attrs
import cirq
from attrs import frozen

from qualtran import bloq_example, BloqBuilder, BloqDocSpec, BQUInt, QAny, QBit, Register, SoquetT
from qualtran._infra.single_qubit_controlled import SpecializedSingleQubitControlledExtension
from qualtran import (
AddControlledT,
Bloq,
bloq_example,
BloqBuilder,
BloqDocSpec,
BQUInt,
CtrlSpec,
QAny,
QBit,
Register,
SoquetT,
)
from qualtran.bloqs.basic_gates import SGate
from qualtran.bloqs.multiplexers.select_base import SelectOracle
from qualtran.bloqs.multiplexers.selected_majorana_fermion import SelectedMajoranaFermion
Expand All @@ -30,7 +42,7 @@


@frozen
class SelectSparse(SpecializedSingleQubitControlledExtension, SelectOracle): # type: ignore[misc]
class SelectSparse(SelectOracle):
r"""SELECT oracle for the sparse Hamiltonian.
Implements the two applications of Fig. 13.
Expand Down Expand Up @@ -157,6 +169,19 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT':
c_maj_y = SelectedMajoranaFermion(sel_pa, target_gate=cirq.Y)
return {SGate(): 1, maj_x: 1, c_maj_x: 1, maj_y: 1, c_maj_y: 1}

def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> Tuple['Bloq', 'AddControlledT']:
from qualtran.bloqs.mcmt.specialized_ctrl import get_ctrl_system_1bit_cv

return get_ctrl_system_1bit_cv(
self,
ctrl_spec=ctrl_spec,
current_ctrl_bit=self.control_val,
get_ctrl_bloq_and_ctrl_reg_name=lambda cv: (
attrs.evolve(self, control_val=cv),
'control',
),
)


@bloq_example
def _sel_sparse() -> SelectSparse:
Expand Down
15 changes: 13 additions & 2 deletions qualtran/bloqs/chemistry/thc/select_bloq.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@
from attrs import evolve, frozen

from qualtran import (
AddControlledT,
Bloq,
bloq_example,
BloqBuilder,
BloqDocSpec,
BQUInt,
CtrlSpec,
QAny,
QBit,
Register,
Signature,
SoquetT,
)
from qualtran._infra.single_qubit_controlled import SpecializedSingleQubitControlledExtension
from qualtran.bloqs.basic_gates import CSwap, Toffoli, XGate
from qualtran.bloqs.chemistry.black_boxes import ApplyControlledZs
from qualtran.bloqs.multiplexers.select_base import SelectOracle
Expand Down Expand Up @@ -120,7 +121,7 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT':


@frozen
class SelectTHC(SpecializedSingleQubitControlledExtension, SelectOracle): # type: ignore[misc]
class SelectTHC(SelectOracle):
r"""SELECT for THC Hamiltonian.
Args:
Expand Down Expand Up @@ -313,6 +314,16 @@ def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: 'SoquetT') -> Dict[str

return out_soqs

def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> Tuple['Bloq', 'AddControlledT']:
from qualtran.bloqs.mcmt.specialized_ctrl import get_ctrl_system_1bit_cv

return get_ctrl_system_1bit_cv(
self,
ctrl_spec=ctrl_spec,
current_ctrl_bit=self.control_val,
get_ctrl_bloq_and_ctrl_reg_name=lambda cv: (evolve(self, control_val=cv), 'control'),
)


@bloq_example
def _thc_sel() -> SelectTHC:
Expand Down
19 changes: 16 additions & 3 deletions qualtran/bloqs/for_testing/random_select_and_prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
from functools import cached_property
from typing import Iterator, Optional, Tuple

import attrs
import cirq
import numpy as np
from attrs import frozen
from numpy.typing import NDArray

from qualtran import BloqBuilder, BQUInt, QBit, Register, SoquetT
from qualtran._infra.single_qubit_controlled import SpecializedSingleQubitControlledExtension
from qualtran import AddControlledT, Bloq, BloqBuilder, BQUInt, CtrlSpec, QBit, Register, SoquetT
from qualtran.bloqs.block_encoding.lcu_block_encoding import SelectBlockEncoding
from qualtran.bloqs.for_testing.matrix_gate import MatrixGate
from qualtran.bloqs.multiplexers.select_base import SelectOracle
Expand Down Expand Up @@ -84,7 +84,7 @@ def alphas(self):


@frozen
class TestPauliSelectOracle(SpecializedSingleQubitControlledExtension, SelectOracle): # type: ignore[misc]
class TestPauliSelectOracle(SelectOracle): # type: ignore[misc]
r"""Paulis acting on $m$ qubits, controlled by an $n$-qubit register.
Given $2^n$ multi-qubit-Paulis (acting on $m$ qubits) $U_j$,
Expand Down Expand Up @@ -149,6 +149,19 @@ def decompose_from_registers(
op = op.controlled_by(*quregs['control'], control_values=[self.control_val])
yield op

def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> Tuple['Bloq', 'AddControlledT']:
from qualtran.bloqs.mcmt.specialized_ctrl import get_ctrl_system_1bit_cv

return get_ctrl_system_1bit_cv(
self,
ctrl_spec=ctrl_spec,
current_ctrl_bit=self.control_val,
get_ctrl_bloq_and_ctrl_reg_name=lambda cv: (
attrs.evolve(self, control_val=cv),
'control',
),
)


def random_qubitization_walk_operator(
select_bitsize: int, target_bitsize: int, *, random_state: np.random.RandomState
Expand Down
3 changes: 1 addition & 2 deletions qualtran/bloqs/mcmt/controlled_via_and.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ def _is_single_bit_control(self) -> bool:

@cached_property
def _single_control_value(self) -> int:
assert self._is_single_bit_control()
return self.ctrl_spec._cvs_tuple[0]
return self.ctrl_spec.get_single_ctrl_bit()

def adjoint(self) -> 'ControlledViaAnd':
return ControlledViaAnd(self.subbloq.adjoint(), self.ctrl_spec)
Expand Down
Loading

0 comments on commit a83d49d

Please sign in to comment.