Skip to content

Commit 601c676

Browse files
Pull envelope into base Hamming weight PDF
1 parent 7b7030d commit 601c676

4 files changed

Lines changed: 58 additions & 60 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
77

88
[project]
99
name = "pyqrackising"
10-
version = "9.15.0"
10+
version = "9.15.1"
1111
requires-python = ">=3.8"
1212
description = "Fast MAXCUT, TSP, and sampling heuristics from near-ideal transverse field Ising model (TFIM)"
1313
readme = {file = "README.txt", content-type = "text/markdown"}

pyqrackising/generate_tfim_samples.py

Lines changed: 5 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ def sample_fixed_hamming_weight(h_weight, count, n_rows, n_cols, burnin=10):
176176
return samples
177177

178178

179-
@njit
179+
@njit(cache=True)
180180
def factor_width(width, is_transpose=False):
181181
col_len = math.floor(math.sqrt(width))
182182
while ((width // col_len) * col_len) != width:
@@ -186,7 +186,7 @@ def factor_width(width, is_transpose=False):
186186
return (col_len, row_len) if is_transpose else (row_len, col_len)
187187

188188

189-
@njit
189+
@njit(cache=True)
190190
def comb(n, k):
191191
if (k < 0) or (k > n):
192192
return 0
@@ -198,7 +198,7 @@ def comb(n, k):
198198
return res
199199

200200

201-
@njit
201+
@njit(cache=True)
202202
def fix_cdf(hamming_prob):
203203
tot_prob = 0.0
204204
n_bias = len(hamming_prob)
@@ -211,55 +211,7 @@ def fix_cdf(hamming_prob):
211211
return cum_prob
212212

213213

214-
@njit
215-
def _apply_time_envelope(bias, t, n_qubits):
216-
"""
217-
Multiply bias[k] by exp(-|k - n/2| / max(t, epsilon)) for each k.
218-
219-
This is the time-dependent Hamming weight envelope:
220-
- At small t: peaks sharply at half-filling k = n/2 (AFM sector).
221-
- At large t: envelope -> 1, recovering the original bias exactly.
222-
223-
The differential effect is greatest at initialization (small t),
224-
which is where the ESD / adiabatic physics lives.
225-
226-
alpha = 1.0 is hardcoded as the natural physical invariant.
227-
It is the least contrived value that produces the correct qualitative
228-
behaviour, and is left fixed rather than tuned empirically.
229-
230-
Authors: Claude (Anthropic) and D. Strano
231-
"""
232-
alpha = 1.0
233-
half = n_qubits / 2.0
234-
# Numba-safe floor of t for the epsilon guard
235-
t_eff = t if t > 1e-9 else 1e-9
236-
237-
out = np.empty(n_qubits + 1, dtype=np.float64)
238-
tot = 0.0
239-
for k in range(n_qubits + 1):
240-
dist = k - half
241-
if dist < 0.0:
242-
dist = -dist
243-
envelope = math.exp(-alpha * dist / t_eff)
244-
val = bias[k] * envelope
245-
out[k] = val
246-
tot += val
247-
248-
if tot <= 0.0:
249-
# Pathological underflow: collapse to half-filling delta
250-
for k in range(n_qubits + 1):
251-
out[k] = 0.0
252-
mid = n_qubits // 2
253-
out[mid] = 1.0
254-
return out
255-
256-
for k in range(n_qubits + 1):
257-
out[k] /= tot
258-
259-
return out
260-
261-
262-
@njit
214+
@njit(cache=True)
263215
def get_tfim_hamming_distribution(J=-1.0, h=2.0, z=4, theta=0.174532925199432957, t=5, n_qubits=56, omega=1.5 * np.pi):
264216
if abs(t) <= epsilon:
265217
p = (1.0 - np.cos(theta)) / 2.0
@@ -277,11 +229,7 @@ def get_tfim_hamming_distribution(J=-1.0, h=2.0, z=4, theta=0.174532925199432957
277229
bias[0] = 1.0
278230
return bias
279231

280-
bias = probability_by_hamming_weight(J, h, z, theta, t, n_qubits + 1, normalized=True, omega=omega)
281-
282-
# Apply time-dependent envelope: maximum differential at small t,
283-
# recovers original distribution as t -> inf.
284-
return _apply_time_envelope(bias / bias.sum(), t, n_qubits)
232+
return probability_by_hamming_weight(J, h, z, theta, t, n_qubits + 1, normalized=True, omega=omega)
285233

286234

287235
def generate_tfim_samples(J=-1.0, h=2.0, z=4, theta=0.174532925199432957, t=5, n_qubits=56, shots=100):

pyqrackising/maxcut_tfim_util.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,54 @@ def init_thresholds(n_qubits):
617617
return thresholds
618618

619619

620+
@njit(cache=True)
621+
def _apply_time_envelope(bias, t, n_qubits):
622+
"""
623+
Multiply bias[k] by exp(-|k - n/2| / max(t, epsilon)) for each k.
624+
625+
This is the time-dependent Hamming weight envelope:
626+
- At small t: peaks sharply at half-filling k = n/2 (AFM sector).
627+
- At large t: envelope -> 1, recovering the original bias exactly.
628+
629+
The differential effect is greatest at initialization (small t),
630+
which is where the ESD / adiabatic physics lives.
631+
632+
alpha = 1.0 is hardcoded as the natural physical invariant.
633+
It is the least contrived value that produces the correct qualitative
634+
behaviour, and is left fixed rather than tuned empirically.
635+
636+
Authors: Claude (Anthropic) and D. Strano
637+
"""
638+
alpha = 1.0
639+
half = n_qubits / 2.0
640+
# Numba-safe floor of t for the epsilon guard
641+
t_eff = t if t > 1e-9 else 1e-9
642+
643+
out = np.empty(n_qubits + 1, dtype=np.float64)
644+
tot = 0.0
645+
for k in range(n_qubits + 1):
646+
dist = k - half
647+
if dist < 0.0:
648+
dist = -dist
649+
envelope = math.exp(-alpha * dist / t_eff)
650+
val = bias[k] * envelope
651+
out[k] = val
652+
tot += val
653+
654+
if tot <= 0.0:
655+
# Pathological underflow: collapse to half-filling delta
656+
for k in range(n_qubits + 1):
657+
out[k] = 0.0
658+
mid = n_qubits // 2
659+
out[mid] = 1.0
660+
return out
661+
662+
for k in range(n_qubits + 1):
663+
out[k] /= tot
664+
665+
return out
666+
667+
620668
@njit(cache=True)
621669
def probability_by_hamming_weight(J, h, z, theta, t, n_bias, normalized=True, omega=1.5 * np.pi):
622670
zJ = z * J
@@ -640,7 +688,9 @@ def probability_by_hamming_weight(J, h, z, theta, t, n_bias, normalized=True, om
640688
if normalized:
641689
bias /= bias.sum()
642690

643-
return bias
691+
# Apply time-dependent envelope: maximum differential at small t,
692+
# recovers original distribution as t -> inf.
693+
return _apply_time_envelope(bias / bias.sum(), t, n_bias - 1)
644694

645695

646696
@njit(cache=True)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
setup(
99
name="pyqrackising",
10-
version="9.15.0",
10+
version="9.15.1",
1111
author="Dan Strano",
1212
author_email="stranoj@gmail.com",
1313
description="Fast MAXCUT, TSP, and sampling heuristics from near-ideal transverse field Ising model (TFIM)",

0 commit comments

Comments
 (0)