| """ |
| Try functions with specific sparse support patterns. |
| |
| Key insight: The autocorrelation inequality is related to additive combinatorics. |
| For a set S, the autoconvolution (1_S * 1_S)(t) counts pairs (a,b) in S with a+b=t. |
| To minimize max(f*f)/(∫f)², we want the "sumset" S+S to be as uniformly distributed as possible. |
| |
| This is related to: |
| - B_h sets (Sidon sets) |
| - Difference sets |
| - Constructions from finite fields |
| |
| Let me try constructions inspired by these. |
| """ |
| import numpy as np |
| from scipy.optimize import minimize |
| import time |
|
|
| def compute_c1_fft(f_values, dx): |
| f = np.maximum(f_values, 0.0) |
| N = len(f) |
| M = 2 * N |
| fft_f = np.fft.rfft(f, n=M) |
| conv = np.fft.irfft(fft_f * fft_f, n=M) * dx |
| integral_sq = (np.sum(f) * dx) ** 2 |
| if integral_sq < 1e-20: |
| return 1e10 |
| return float(np.max(conv) / integral_sq) |
|
|
| def compute_c1_smooth_and_grad(f, N, dx, alpha=200.0): |
| M = 2 * N |
| fft_f = np.fft.rfft(f, n=M) |
| conv = np.fft.irfft(fft_f * fft_f, n=M) * dx |
| integral = np.sum(f) * dx |
| if integral < 1e-15: |
| return 1e10, np.zeros(N) |
| integral_sq = integral ** 2 |
| max_val = np.max(conv) |
| shifted = conv - max_val |
| mask = shifted > -50.0 / alpha |
| weights = np.zeros_like(conv) |
| weights[mask] = np.exp(alpha * shifted[mask]) |
| sum_w = np.sum(weights) |
| if sum_w < 1e-30: |
| weights[np.argmax(conv)] = 1.0 |
| sum_w = 1.0 |
| smooth_max = max_val + np.log(sum_w) / alpha |
| softmax_w = weights / sum_w |
| c1 = smooth_max / integral_sq |
| fft_sw = np.fft.rfft(softmax_w, n=M) |
| fft_fp = np.fft.rfft(f, n=M) |
| corr = np.fft.irfft(fft_sw * np.conj(fft_fp), n=M) |
| grad_f = 2.0 * corr[:N] * dx / integral_sq - 2.0 * smooth_max * dx / (integral**3) |
| return c1, grad_f |
|
|
| def full_opt(f_init, N, dx, maxiter=3000): |
| params = np.sqrt(np.maximum(f_init, 0.0) + 1e-12) |
| for alpha in [0.5, 2.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0]: |
| def obj(p, a=alpha): |
| f = p ** 2 |
| c1, g = compute_c1_smooth_and_grad(f, N, dx, a) |
| return c1, g * 2 * p |
| result = minimize(obj, params, jac=True, method='L-BFGS-B', |
| options={'maxiter': maxiter, 'ftol': 1e-16, 'gtol': 1e-15}) |
| params = result.x |
| f_out = params ** 2 |
| return f_out, compute_c1_fft(f_out, dx) |
|
|
| N = 2000 |
| dx = 0.5 / N |
|
|
| |
| |
| print("=== Quadratic Residue Sets ===") |
| for p in [7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]: |
| qr = set() |
| for a in range(p): |
| qr.add((a * a) % p) |
| |
| f = np.zeros(N) |
| for r in qr: |
| |
| block_start = int(r * N / p) |
| block_end = int((r + 1) * N / p) |
| f[block_start:block_end] = 1.0 |
| c1_raw = compute_c1_fft(f, dx) |
| f_opt, c1_opt = full_opt(f, N, dx) |
| if c1_opt < 1.51: |
| print(f" p={p}: raw C1={c1_raw:.6f}, optimized C1={c1_opt:.10f} ***") |
| elif p <= 31 or c1_opt < 1.515: |
| print(f" p={p}: raw C1={c1_raw:.6f}, optimized C1={c1_opt:.10f}") |
|
|
| |
| print("\n=== Paley-type ===") |
| for p in [23, 29, 31, 37, 41, 43, 47]: |
| |
| leg = np.zeros(p) |
| for a in range(1, p): |
| leg[a] = 1 if pow(a, (p-1)//2, p) == 1 else -1 |
|
|
| |
| indicator = (1 + leg) / 2 |
|
|
| |
| f = np.zeros(N) |
| for i in range(p): |
| block_start = int(i * N / p) |
| block_end = int((i + 1) * N / p) |
| f[block_start:block_end] = indicator[i] |
|
|
| f_opt, c1 = full_opt(f, N, dx) |
| print(f" p={p}: C1 = {c1:.10f}") |
|
|
| |
| |
| |
| print("\n=== Difference Sets ===") |
|
|
| |
| |
| |
| |
| |
| |
|
|
| diff_sets = { |
| 7: [0, 1, 3], |
| 13: [0, 1, 3, 9], |
| 21: [0, 1, 5, 11, 13], |
| 31: [0, 1, 3, 8, 12, 18], |
| 57: [0, 1, 3, 13, 32, 36, 43, 52], |
| 73: [0, 1, 3, 7, 15, 31, 36, 54, 63], |
| 91: [0, 1, 3, 9, 27, 49, 56, 61, 77, 81], |
| } |
|
|
| for v, D in diff_sets.items(): |
| f = np.zeros(N) |
| for d in D: |
| block_start = int(d * N / v) |
| block_end = int((d + 1) * N / v) |
| f[block_start:block_end] = 1.0 |
|
|
| c1_raw = compute_c1_fft(f, dx) |
| f_opt, c1 = full_opt(f, N, dx) |
| print(f" ({v},{len(D)},1): raw={c1_raw:.6f}, opt={c1:.10f}") |
|
|
| |
| print("\n=== Multi-scale ===") |
| for n_scales in [2, 3, 4, 5]: |
| for seed in range(5): |
| np.random.seed(seed * 100 + n_scales) |
| f = np.zeros(N) |
| for scale in range(n_scales): |
| block_size = N // (3 ** (scale + 1)) |
| if block_size < 1: |
| break |
| n_blocks = N // block_size |
| |
| selected = np.random.rand(n_blocks) > 0.5 |
| for i in range(n_blocks): |
| if selected[i]: |
| s = i * block_size |
| e = min(s + block_size, N) |
| f[s:e] += 1.0 / (scale + 1) |
|
|
| f_opt, c1 = full_opt(f, N, dx) |
| if c1 < 1.51: |
| print(f" scales={n_scales}, seed={seed}: C1 = {c1:.10f} ***") |
| elif seed == 0: |
| print(f" scales={n_scales}, seed={seed}: C1 = {c1:.10f}") |
|
|
| |
| print("\n=== Fractal constructions ===") |
| for removal_frac in [1/3, 1/4, 1/5, 2/5, 1/2]: |
| for levels in [1, 2, 3, 4, 5]: |
| f = np.ones(N) |
| for level in range(levels): |
| block_size = N // (int(1/removal_frac) + 1) ** (level + 1) |
| if block_size < 1: |
| break |
| n_blocks = N // block_size |
| for b in range(n_blocks): |
| |
| start = b * block_size |
| mid_start = start + int(block_size * (1 - removal_frac) / 2) |
| mid_end = start + int(block_size * (1 + removal_frac) / 2) |
| if mid_end <= N: |
| f[mid_start:mid_end] = 0.0 |
|
|
| c1_raw = compute_c1_fft(f, dx) |
| f_opt, c1 = full_opt(f, N, dx) |
| if c1 < 1.515: |
| print(f" remove={removal_frac:.2f} levels={levels}: raw={c1_raw:.4f}, opt={c1:.10f}") |
|
|
| |
| print("\n=== Tiling approach ===") |
| |
| for N_small in [50, 100, 200]: |
| dx_small = 0.5 / N_small |
| best_c1_small = np.inf |
| best_f_small = None |
|
|
| for seed in range(100): |
| np.random.seed(seed + 7000) |
| f_init = np.abs(np.random.randn(N_small)) + 0.1 |
| f_opt, c1 = full_opt(f_init, N_small, dx_small, maxiter=1000) |
| if c1 < best_c1_small: |
| best_c1_small = c1 |
| best_f_small = f_opt |
|
|
| print(f" Best at N={N_small}: C1 = {best_c1_small:.10f}") |
|
|
| |
| repeats = N // N_small |
| f_tiled = np.tile(best_f_small, repeats)[:N] |
| c1_tiled = compute_c1_fft(f_tiled, dx) |
| f_opt_tiled, c1_opt_tiled = full_opt(f_tiled, N, dx) |
| print(f" Tiled raw: C1 = {c1_tiled:.10f}, optimized: C1 = {c1_opt_tiled:.10f}") |
|
|