| |
| import numpy as np |
| from scipy.optimize import minimize |
| from scipy.interpolate import interp1d |
| import time |
|
|
|
|
| def compute_c1(f_values, dx): |
| f = np.maximum(f_values, 0.0) |
| autoconv = np.convolve(f, f, mode='full') * dx |
| integral_sq = (np.sum(f) * dx) ** 2 |
| if integral_sq < 1e-20: |
| return 1e10 |
| return float(np.max(autoconv) / integral_sq) |
|
|
|
|
| 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 opt(params, N, dx, alpha, maxiter, method='L-BFGS-B'): |
| def obj(p, a=alpha): |
| f = p ** 2 |
| c1, g = compute_c1_smooth_and_grad(f, N, dx, a) |
| return c1, g * 2 * p |
| if method == 'CG': |
| result = minimize(obj, params, jac=True, method='CG', |
| options={'maxiter': maxiter, 'gtol': 1e-12}) |
| else: |
| result = minimize(obj, params, jac=True, method='L-BFGS-B', |
| options={'maxiter': maxiter, 'ftol': 1e-16, 'gtol': 1e-15}) |
| return result.x |
|
|
|
|
| def upscale(f, N_new): |
| N_old = len(f) |
| x_old = np.linspace(0, 1, N_old) |
| x_new = np.linspace(0, 1, N_new) |
| interp = interp1d(x_old, f, kind='linear', fill_value=0.0, bounds_error=False) |
| return np.maximum(interp(x_new), 0.0) |
|
|
|
|
| def run(): |
| t0 = time.time() |
|
|
| N = 10000 |
| dx = 0.5 / N |
|
|
| |
| try: |
| f_loaded = np.load('/workspace/best_f_10000.npy') |
| if len(f_loaded) == N: |
| best_c1 = compute_c1_fft(f_loaded, dx) |
| best_f = f_loaded.copy() |
| print(f"Loaded N={N}: C1 = {best_c1:.10f}") |
| else: |
| raise FileNotFoundError |
| except: |
| try: |
| |
| best_5k_c1 = np.inf |
| f_5k = None |
| for fname in ['/workspace/best_f_5000_hard.npy', '/workspace/best_f_5000.npy']: |
| try: |
| f_tmp = np.load(fname) |
| c1_tmp = compute_c1_fft(f_tmp, 0.5/len(f_tmp)) |
| if c1_tmp < best_5k_c1: |
| best_5k_c1 = c1_tmp |
| f_5k = f_tmp |
| except: |
| pass |
| if f_5k is None: |
| raise FileNotFoundError |
| f_init = upscale(f_5k, N) |
| except: |
| |
| np.random.seed(684) |
| f_150 = np.ones(150) + 0.3 * np.random.randn(150) |
| f_150 = np.maximum(f_150, 0.01) |
| params = np.sqrt(f_150 + 1e-12) |
| for alpha in [50, 500, 5000]: |
| params = opt(params, 150, 0.5/150, alpha, 500) |
| f_init = upscale(params ** 2, N) |
|
|
| params = np.sqrt(np.maximum(f_init, 0.0) + 1e-12) |
| for alpha in [200.0, 2000.0, 20000.0]: |
| params = opt(params, N, dx, alpha, 5000) |
| best_f = params ** 2 |
| best_c1 = compute_c1_fft(best_f, dx) |
| print(f"From upscale: C1 = {best_c1:.10f}") |
|
|
| params = np.sqrt(np.maximum(best_f, 0.0) + 1e-12) |
|
|
| |
| print(f"\nAlpha cycling at N={N}:") |
| cycle = 0 |
| while time.time() - t0 < 1500: |
| |
| for alpha in [0.5, 2.0, 10.0]: |
| params = opt(params, N, dx, alpha, 500) |
| |
| for alpha in [100.0, 1000.0]: |
| params = opt(params, N, dx, alpha, 1000) |
| |
| for alpha in [10000.0, 100000.0]: |
| params = opt(params, N, dx, alpha, 2000) |
| |
| if cycle % 3 == 2: |
| params = opt(params, N, dx, 10000.0, 2000, method='CG') |
| params = opt(params, N, dx, 100000.0, 2000) |
|
|
| f_out = params ** 2 |
| c1 = compute_c1_fft(f_out, dx) |
| if c1 < best_c1: |
| best_c1 = c1 |
| best_f = f_out.copy() |
| if cycle % 5 == 0: |
| print(f" Cycle {cycle}: C1 = {c1:.10f}, t={time.time()-t0:.0f}s") |
| cycle += 1 |
|
|
| print(f" Total cycles: {cycle}, C1: {best_c1:.10f}") |
|
|
| |
| params = np.sqrt(np.maximum(best_f, 0.0) + 1e-12) |
| params = opt(params, N, dx, 1000000.0, 15000) |
| f_out = params ** 2 |
| c1 = compute_c1_fft(f_out, dx) |
| if c1 < best_c1: |
| best_c1 = c1 |
| best_f = f_out.copy() |
|
|
| print(f"\nFinal C1 (FFT): {best_c1:.10f}") |
| print(f"Score: {1.5052939684401607 / best_c1:.10f}") |
|
|
| |
| f_out = np.maximum(best_f, 0.0) |
| np.save('/workspace/best_f_10000.npy', f_out) |
|
|
| |
| autoconv = np.convolve(f_out, f_out, mode='full') * dx |
| integral_sq = (np.sum(f_out) * dx) ** 2 |
| c1_final = float(np.max(autoconv / integral_sq)) |
|
|
| print(f"C1 (exact): {c1_final:.10f}") |
|
|
| return f_out, c1_final, c1_final, N |
|
|
|
|
| |
|
|