Skip to content

Commit a1e13d4

Browse files
committed
adjoints, fix guiding state overlap
1 parent 96cd9df commit a1e13d4

File tree

7 files changed

+63
-12
lines changed

7 files changed

+63
-12
lines changed

qualtran/bloqs/max_k_xor_sat/arithmetic/equals.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,6 @@ def build_composite_bloq(
5959

6060
def build_call_graph(self, ssa: 'SympySymbolAllocator') -> BloqCountDictT:
6161
return {Xor(QAny(self.bitsize)): 2, MultiControlX(cvs=HasLength(self.bitsize)): 1}
62+
63+
def adjoint(self) -> 'Bloq':
64+
return self

qualtran/bloqs/max_k_xor_sat/guided_hamiltonian/walk_operator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,6 @@ def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: 'SoquetT') -> dict[str
8989

9090
def build_call_graph(self, ssa: 'SympySymbolAllocator') -> BloqCountDictT:
9191
return {self.block_encoding: 1, self.reflect: 1}
92+
93+
def __str__(self):
94+
return f'Walk[{self.block_encoding}]'

qualtran/bloqs/max_k_xor_sat/kikuchi_adjacency_list.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ def signature(self) -> 'Signature':
9999
def index_bitsize(self) -> SymbolicInt:
100100
return self.ell * self.inst.index_bitsize
101101

102+
def adjoint(self) -> 'ColumnOfKthNonZeroEntry':
103+
return self
104+
102105
def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT':
103106
m = self.inst.num_unique_constraints
104107
ell, k = self.ell, self.inst.k
@@ -206,6 +209,9 @@ def signature(self) -> 'Signature':
206209
def index_bitsize(self) -> SymbolicInt:
207210
return self.ell * self.inst.index_bitsize
208211

212+
def adjoint(self) -> 'IndexOfNonZeroColumn':
213+
return self
214+
209215
def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT':
210216
m = self.inst.num_unique_constraints
211217
ell, k = self.ell, self.inst.k

qualtran/bloqs/max_k_xor_sat/kikuchi_block_encoding.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ def signal_state(self) -> BlackBoxPrepare:
205205
def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: 'SoquetT') -> dict[str, 'SoquetT']:
206206
return bb.add_d(self._sparse_matrix_encoding, **soqs)
207207

208+
def __str__(self):
209+
return 'B[K_l]'
210+
208211

209212
@bloq_example
210213
def _kikuchi_matrix() -> KikuchiHamiltonian:

qualtran/bloqs/max_k_xor_sat/planted_noisy_kxor.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import numpy as np
1818
import scipy
1919
import sympy
20-
from attrs import frozen
20+
from attrs import field, frozen
2121

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

223224
def __attrs_post_init__(self):
224225
k = self.inst_guide.k
@@ -242,6 +243,7 @@ def from_inst(
242243
*,
243244
zeta: Optional[SymbolicFloat],
244245
rng: np.random.Generator,
246+
guiding_state_overlap: Optional[SymbolicFloat] = None,
245247
):
246248
(use_for_guide,) = np.nonzero(np.atleast_1d(rng.random(inst.m) < zeta))
247249
inst_guide = inst.subset(tuple(use_for_guide))
@@ -254,7 +256,13 @@ def from_inst(
254256
(rest,) = np.nonzero(mask)
255257
inst_solve = inst.subset(tuple(rest))
256258

257-
return cls(inst_guide=inst_guide, inst_solve=inst_solve, ell=ell, rho=rho)
259+
return cls(
260+
inst_guide=inst_guide,
261+
inst_solve=inst_solve,
262+
ell=ell,
263+
rho=rho,
264+
guiding_state_overlap=guiding_state_overlap,
265+
)
258266

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

297+
@cached_property
298+
def guiding_state_overlap(self) -> SymbolicFloat:
299+
if self._guiding_state_overlap is not None:
300+
return self.guiding_state_overlap
301+
_, guiding_state_good_coeff = self.guiding_state_and_coefficient
302+
return guiding_state_good_coeff
303+
289304
@cached_property
290305
def overlap(self) -> SymbolicFloat:
291306
# guiding state
292-
_, guiding_state_good_coeff = self.guiding_state_and_coefficient
307+
guiding_state_good_coeff = self.guiding_state_overlap
293308

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

334351
guiding_state, _ = self.guiding_state_and_coefficient
335352

qualtran/bloqs/max_k_xor_sat/planted_noisy_kxor_test.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,7 @@ def test_call_graph_symb():
6464
show_call_graph(g)
6565

6666

67-
def example_random_instance() -> PlantedNoisyKXOR:
68-
# configure parameters here
69-
k = 4
70-
n, m = 100, 1000
71-
rho = 0.8
72-
seed = 120
73-
74-
c = 2 # Kikuchi param: ell = c * k
75-
67+
def example_random_instance(*, k=4, n=100, m=1000, c=2, rho=0.8, seed=120) -> PlantedNoisyKXOR:
7668
# generate instance
7769
rng = np.random.default_rng(seed)
7870
ell = c * k
@@ -97,3 +89,24 @@ def test_gate_cost():
9789
print(t_cost)
9890
print(t_cost / big_O_expected)
9991
print(big_O_expected)
92+
print(t_cost / big_O_expected * bloq.guiding_state_overlap)
93+
print(1 / bloq.guiding_state_overlap)
94+
print(1 / bloq.guiding_state_overlap_guarantee.overlap_probability**0.5)
95+
96+
97+
@pytest.mark.parametrize("n", [40, 50, 60, 70, 80, 90, 100])
98+
@pytest.mark.parametrize("k", [4, 8])
99+
@pytest.mark.parametrize("c", [2, 3, 4])
100+
def test_more_costs(n, k, c):
101+
bloq = example_random_instance(k=k, c=c, n=n, m=n, seed=142)
102+
cost = get_cost_value(bloq, QECGatesCost())
103+
print(cost)
104+
105+
106+
@pytest.mark.parametrize("n", [10**4, 10**5])
107+
def test_large(n):
108+
k = 4
109+
c = 32 // 4
110+
bloq = example_random_instance(k=k, c=c, n=n, m=n * 10, seed=142)
111+
cost = get_cost_value(bloq, QECGatesCost())
112+
print(cost)

qualtran/bloqs/mcmt/multi_control_pauli.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ class MultiControlX(MultiControlPauli):
191191
def _X(self):
192192
return cirq.X
193193

194+
def adjoint(self) -> 'Bloq':
195+
return self
196+
194197

195198
@frozen
196199
class MultiControlZ(MultiControlPauli):
@@ -203,3 +206,6 @@ class MultiControlZ(MultiControlPauli):
203206
@target_gate.default
204207
def _Z(self):
205208
return cirq.Z
209+
210+
def adjoint(self) -> 'Bloq':
211+
return self

0 commit comments

Comments
 (0)