Skip to content

Commit

Permalink
adjoints, fix guiding state overlap
Browse files Browse the repository at this point in the history
  • Loading branch information
anurudhp committed Sep 19, 2024
1 parent 96cd9df commit a1e13d4
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 12 deletions.
3 changes: 3 additions & 0 deletions qualtran/bloqs/max_k_xor_sat/arithmetic/equals.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ def build_composite_bloq(

def build_call_graph(self, ssa: 'SympySymbolAllocator') -> BloqCountDictT:
return {Xor(QAny(self.bitsize)): 2, MultiControlX(cvs=HasLength(self.bitsize)): 1}

def adjoint(self) -> 'Bloq':
return self
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,6 @@ def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: 'SoquetT') -> dict[str

def build_call_graph(self, ssa: 'SympySymbolAllocator') -> BloqCountDictT:
return {self.block_encoding: 1, self.reflect: 1}

def __str__(self):
return f'Walk[{self.block_encoding}]'
6 changes: 6 additions & 0 deletions qualtran/bloqs/max_k_xor_sat/kikuchi_adjacency_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ def signature(self) -> 'Signature':
def index_bitsize(self) -> SymbolicInt:
return self.ell * self.inst.index_bitsize

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

def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT':
m = self.inst.num_unique_constraints
ell, k = self.ell, self.inst.k
Expand Down Expand Up @@ -206,6 +209,9 @@ def signature(self) -> 'Signature':
def index_bitsize(self) -> SymbolicInt:
return self.ell * self.inst.index_bitsize

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

def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT':
m = self.inst.num_unique_constraints
ell, k = self.ell, self.inst.k
Expand Down
3 changes: 3 additions & 0 deletions qualtran/bloqs/max_k_xor_sat/kikuchi_block_encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ def signal_state(self) -> BlackBoxPrepare:
def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: 'SoquetT') -> dict[str, 'SoquetT']:
return bb.add_d(self._sparse_matrix_encoding, **soqs)

def __str__(self):
return 'B[K_l]'


@bloq_example
def _kikuchi_matrix() -> KikuchiHamiltonian:
Expand Down
23 changes: 20 additions & 3 deletions qualtran/bloqs/max_k_xor_sat/planted_noisy_kxor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import numpy as np
import scipy
import sympy
from attrs import frozen
from attrs import field, frozen

from qualtran import Bloq, bloq_example, BloqBuilder, BloqDocSpec, Signature, SoquetT
from qualtran.bloqs.state_preparation.black_box_prepare import BlackBoxPrepare
Expand Down Expand Up @@ -219,6 +219,7 @@ class PlantedNoisyKXOR(Bloq):
inst_solve: KXorInstance
ell: SymbolicInt
rho: SymbolicFloat
_guiding_state_overlap: Optional[SymbolicFloat] = field(kw_only=True, default=None)

def __attrs_post_init__(self):
k = self.inst_guide.k
Expand All @@ -242,6 +243,7 @@ def from_inst(
*,
zeta: Optional[SymbolicFloat],
rng: np.random.Generator,
guiding_state_overlap: Optional[SymbolicFloat] = None,
):
(use_for_guide,) = np.nonzero(np.atleast_1d(rng.random(inst.m) < zeta))
inst_guide = inst.subset(tuple(use_for_guide))
Expand All @@ -254,7 +256,13 @@ def from_inst(
(rest,) = np.nonzero(mask)
inst_solve = inst.subset(tuple(rest))

return cls(inst_guide=inst_guide, inst_solve=inst_solve, ell=ell, rho=rho)
return cls(
inst_guide=inst_guide,
inst_solve=inst_solve,
ell=ell,
rho=rho,
guiding_state_overlap=guiding_state_overlap,
)

@cached_property
def guiding_state_and_coefficient(self) -> tuple[PrepareOracle, SymbolicFloat]:
Expand Down Expand Up @@ -286,10 +294,17 @@ def guiding_state_overlap_guarantee(self) -> GuidingStateOverlapTheorem:
n=n, k=k, ell=self.ell, m_hat=m_hat, zeta=zeta, nu=1 / ln(n), eps=0.005, rho=self.rho
)

@cached_property
def guiding_state_overlap(self) -> SymbolicFloat:
if self._guiding_state_overlap is not None:
return self.guiding_state_overlap
_, guiding_state_good_coeff = self.guiding_state_and_coefficient
return guiding_state_good_coeff

@cached_property
def overlap(self) -> SymbolicFloat:
# guiding state
_, guiding_state_good_coeff = self.guiding_state_and_coefficient
guiding_state_good_coeff = self.guiding_state_overlap

# overlap of |\Gamma(A)> with the threshold eigenspace
overlap_good_eigen = self.guiding_state_overlap_guarantee.overlap_probability**0.5
Expand Down Expand Up @@ -330,6 +345,8 @@ def guided_hamiltonian_bloq(self) -> GuidedHamiltonian:
kappa = 0.99 * self.rho
eps = 0.005
alpha = 1 - (kappa + eps) / eigenvalue_threshold
if not is_symbolic(alpha):
assert alpha > 0

guiding_state, _ = self.guiding_state_and_coefficient

Expand Down
31 changes: 22 additions & 9 deletions qualtran/bloqs/max_k_xor_sat/planted_noisy_kxor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,7 @@ def test_call_graph_symb():
show_call_graph(g)


def example_random_instance() -> PlantedNoisyKXOR:
# configure parameters here
k = 4
n, m = 100, 1000
rho = 0.8
seed = 120

c = 2 # Kikuchi param: ell = c * k

def example_random_instance(*, k=4, n=100, m=1000, c=2, rho=0.8, seed=120) -> PlantedNoisyKXOR:
# generate instance
rng = np.random.default_rng(seed)
ell = c * k
Expand All @@ -97,3 +89,24 @@ def test_gate_cost():
print(t_cost)
print(t_cost / big_O_expected)
print(big_O_expected)
print(t_cost / big_O_expected * bloq.guiding_state_overlap)
print(1 / bloq.guiding_state_overlap)
print(1 / bloq.guiding_state_overlap_guarantee.overlap_probability**0.5)


@pytest.mark.parametrize("n", [40, 50, 60, 70, 80, 90, 100])
@pytest.mark.parametrize("k", [4, 8])
@pytest.mark.parametrize("c", [2, 3, 4])
def test_more_costs(n, k, c):
bloq = example_random_instance(k=k, c=c, n=n, m=n, seed=142)
cost = get_cost_value(bloq, QECGatesCost())
print(cost)


@pytest.mark.parametrize("n", [10**4, 10**5])
def test_large(n):
k = 4
c = 32 // 4
bloq = example_random_instance(k=k, c=c, n=n, m=n * 10, seed=142)
cost = get_cost_value(bloq, QECGatesCost())
print(cost)
6 changes: 6 additions & 0 deletions qualtran/bloqs/mcmt/multi_control_pauli.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ class MultiControlX(MultiControlPauli):
def _X(self):
return cirq.X

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


@frozen
class MultiControlZ(MultiControlPauli):
Expand All @@ -203,3 +206,6 @@ class MultiControlZ(MultiControlPauli):
@target_gate.default
def _Z(self):
return cirq.Z

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

0 comments on commit a1e13d4

Please sign in to comment.