天赐范式第187天:让峰开始移动——lag load定量

天赐范式第187天·第一篇:让峰开始移动------lag load定量


摘要

fitness峰以速度v定向移动,理论给出测量滞后lag*=v·(1−β·h²·K)/(β·h²·K)。线性区(v≤0.003)比值0.99-1.00,fit崩溃区lag仍符合公式,丢失区种群丢失峰。


一、接续186-2:fitness峰钉死五篇了,该动了

186-2把漂变主导区画出来了------全链先验机器的第一次应用。但有一个隐含假设从182到186贯穿五篇:fitness峰一直钉死在x*=0.8。栖息地不是恒温箱。

186-2的均值不动点μ*是在静止峰下解的:μ* = TARGET + β·h²\*·K·x\*/(1−β) / 1 + β·h²\*·K/(1−β)。这个不动点假设x*是常数------峰不动,均值才不动。峰一动,这个不动点就跟着动,种群均值在后面追。

问题是:追得上吗?追不上时fitness怎么掉?这就是lag load------环境变化导致的跟踪滞后定量。


二、模型变化------回归目标从固定TARGET到种群均值μ

186模型:g' = TARGET + β·(g_sel − TARGET) + v_mut(固定锚,静止环境)

187模型:g' = μ + β·(g_sel − μ) + v_mut(移动锚,动态环境)

变化只有一处:回归目标从固定TARGET=0.5改为种群均值μ。环境动了,种群的"家"也跟着动。

方差动力学不变:Var(g)' = β²·Var(g_sel) + σ_v²------186-1自洽Var(g)*仍适用,h²*、K*不变。

fitness峰移动:x*(t) = x*_0 + v·gen,v是峰速。


三、理论推导------lag* = v·(1−β·h²·K)/(β·h²·K)

均值更新(回归到μ):μ' = μ + β·h²·(x* − μ)·K

这是以μ为变量的AR(1),输入是x*,响应速率β·h²·K。峰以速度v移动时,稳态滞后:

lag* = v·(1 − β·h²·K) / (β·h²·K)

物理意义:峰每代跑远v,选择每代追回β·h²·K·lag------稳态时追回量等于跑远量。等时滞后(峰x*(t)与同刻均值μ(t)的差)为v/(β·h²·K)=83.3v。代码测的是测量滞后(峰x*(gen)与更新后均值μ(gen+1)的差),比等时滞后少一步峰行程v------lag*=v/c−v=v(1−c)/c,测量口径因子(1−β·h²·K)≈0.988。

滞后负荷(fitness损失):Δfitness ≈ lag*² / (2ω²)(高斯fitness的Taylor展开)。

临界峰速v*:lag大到fitness→0,选择无法运作。lag≈3ω时fitness≈0.01,近似崩溃边界。


四、lag(v)曲线:理论vs数值

固定σ_v=0.02(186-2中心参数),扫peak_v ∈ {0, 0.0005, 0.001, 0.002, 0.003, 0.005, 0.01}。

理论参数(σ_v=0.02自洽):h²*=0.5201,K=0.0769,跟踪速率β·h²·K=0.0120,测量口径因子(1−β·h²·K)=0.9880,等时斜率=1/0.0120=83.3,测量斜率=0.9880/0.0120=82.3。

peak_v lag*理论 lag数值 比值 平均fitness 状态
0.0000 0.0000 0.0006† --- 0.9566 基准
0.0005 0.0411 0.0412 1.00 0.8833 跟踪
0.0010 0.0823 0.0817 0.99 0.6998 跟踪
0.0020 0.1646 0.1625 0.99 0.2773 跟踪
0.0030 0.2469 0.2441 0.99 0.0588 跟踪
0.0050 0.4115 0.4097 1.00 0.0004 fit崩溃
0.0100 0.8230 n/a --- 0.0000 丢失

†有限样本漂移残差。


五、线性区、fit崩溃区与丢失区

线性区(peak_v ≤ 0.003):lag∝v,理论斜率82.3,数值比值0.99-1.00。

测量口径因子(1−β·h²·K)=0.988是理论的核心修正------代码测的是lag=x*(gen)−μ(gen+1)(峰与更新后均值的差),比等时滞后v/(β·h²·K)少一步峰行程v。剩余≈1%偏差来自h²和K随lag增大有微小漂移,理论把它们当常数。

fit崩溃区(peak_v = 0.005):lag=0.41仍符合公式(比值1.00),但fitness=0.0004------lag已远超fitness宽度ω=0.10,fitness指数坍塌。崩溃正是理论的预言:lag大到fitness→0,选择无法运作。

丢失区(peak_v ≥ 0.01):种群完全丢失峰,滞后无良定义(均值停在原地,峰持续远去),lag=n/a。

基准(v=0):lag≈0†,fitness=0.957。 种群均值紧跟峰(回归到μ的模型下静态跟踪近乎完美),fitness只受遗传方差影响。

†lag=0.0006为有限样本漂移残差。


六、结论与弧签名动作

问题 答案
峰移动后种群能跟上吗? 线性区(v≤0.003)能,lag*=v·(1−β·h²·K)/(β·h²·K)定量给出滞后
跟不上时怎样? fit崩溃区(v=0.005)lag仍符合公式但fitness→0;丢失区(v≥0.01)种群丢失峰
理论准吗? 线性区比值0.99-1.00,测量口径因子(1−β·h²·K)≈0.988是核心修正
模型为什么改? 固定TARGET下lag线性增长无稳态;回归到μ后lag有稳态,lag load理论成立

叙事弧:

  • 186-1:Var(g)自洽闭式------全链先验机器建成
  • 186-2:全链先验机器第一次应用------漂变主导区显形
  • 187-1:峰开始移动------lag load定量,从"平衡"升级到"追踪"
  • 弧签名动作:186静止峰平衡 → 187移动峰追踪。

降调:

  1. 准稳态近似。 lag* = v·(1−β·h²·K)/(β·h²·K)假设种群始终贴近瞬时平衡。丢失区(v≥0.01)种群完全丢失峰、滞后无良定义------失效区本身就是发现,如实报。fit崩溃区(v=0.005)lag仍符合公式,但fitness已指数坍塌。

  2. h²和K被当常数。 理论把h²*和K*当固定值(用σ_v=0.02自洽解),但lag增大时种群偏离峰更远,选择强度变化,h²和K有微小漂移。线性区影响≈1%,崩溃区影响大。

  3. 模型变化需说明。 186用固定TARGET=0.5,187改为回归到μ。方差动力学不变(186-1自洽仍适用),但均值动力学变了------固定TARGET下lag无稳态(线性增长),回归到μ后lag有稳态。这个变化是"让峰开始移动"的自然推论:环境动了,种群的"家"也跟着动。

  4. 单位点模型。 多位点、上位效应、连锁不平衡待后续。

系列还在逐步建设中,完善是和伙伴们的努力方向。


附录:完整代码

python 复制代码
# -*- coding: utf-8 -*-
"""
天赐范式 第187天 第一篇
让峰开始移动------lag load定量

PID: TC-187A-V3.3.25.0
V3.3.25.0 · 2026-10-06

接续186-2:fitness峰不再钉死x*=0.8,以速度v定向移动。
模型变化:回归目标从固定TARGET改为种群均值μ(环境动了,种群的"家"也跟着动)
  186模型: g'=TARGET+β(g_sel-TARGET)+v_mut  (固定锚,静止环境)
  187模型: g'=μ+β(g_sel-μ)+v_mut            (移动锚,动态环境)
方差动力学不变(Var(g)'=β²·Var(g_sel)+σ_v²),186-1自洽Var(g)*仍适用。

理论:等时滞后 lag_eq = v/(β·h²·K)(峰x*(t)与同刻均值μ(t)的差)
      测量滞后 lag* = v·(1−β·h²·K)/(β·h²·K)(峰x*(gen)与更新后均值μ(gen+1)的差)
      因子(1−β·h²·K)≈0.988是测量口径因子(非离散修正:离散AR(1)等时滞后恒等于v/c)
      滞后负荷 ≈ lag²/(2ω²)
      临界峰速v*:lag大到fitness→0,选择无法运作
数值:扫peak_v,测lag=x*(gen)−μ(gen+1),判决线性区+崩溃区
"""

import sys
import math
import numpy as np

if hasattr(sys.stdout, "reconfigure"):
    sys.stdout.reconfigure(encoding="utf-8")

PID = "TC-187A-V3.3.25.0"

TARGET = 0.5
X_STAR_0 = 0.8
FITNESS_WIDTH = 0.10
BETA = 0.3
SIGMA_E = 0.02
SIGMA_V = 0.02
N_POP = 200
N_GENERATIONS = 1000
WARMUP_STATIC = 200
WARMUP_TRACK = 200
N_SEEDS = 20
TOL = 1e-12
MAX_ITER = 5000

PEAK_VELOCITIES = [0.0, 0.0005, 0.001, 0.002, 0.003, 0.005, 0.010]


def bar(title):
    print("=" * 72)
    print("  " + title)
    print("=" * 72)
    print()


def sub(title):
    print("【" + title)
    print("-" * 72)


def fitness(x, x_star):
    return np.exp(-(x - x_star) ** 2 / (2 * FITNESS_WIDTH ** 2))


def solve_self_consistent(sigma_v):
    var_g = sigma_v ** 2 / (1 - BETA ** 2)
    for it in range(MAX_ITER):
        sigma_x2 = var_g + SIGMA_E ** 2
        h2 = var_g / sigma_x2
        v_x_sel = sigma_x2 * FITNESS_WIDTH ** 2 / (sigma_x2 + FITNESS_WIDTH ** 2)
        var_g_sel = h2 ** 4 * v_x_sel + var_g * (1 - h2 ** 2)
        var_g_new = BETA ** 2 * var_g_sel + sigma_v ** 2
        if abs(var_g_new - var_g) < TOL:
            return var_g_new, it + 1
        var_g = var_g_new
    return var_g, MAX_ITER


def theory_lag(peak_v):
    var_g_star, _ = solve_self_consistent(SIGMA_V)
    sigma_x2 = var_g_star + SIGMA_E ** 2
    h2 = var_g_star / sigma_x2
    K = sigma_x2 / (sigma_x2 + FITNESS_WIDTH ** 2)
    track_rate = BETA * h2 * K
    measure_factor = 1.0 - track_rate
    lag_star = peak_v * measure_factor / track_rate if track_rate > 0 else float('inf')
    fitness_loss = lag_star ** 2 / (2 * FITNESS_WIDTH ** 2)
    return lag_star, fitness_loss, h2, K, track_rate


def run_one(peak_v, seed):
    rng = np.random.RandomState(seed)
    genes = rng.normal(TARGET, 0.01, N_POP)
    lags = []
    mean_fitnesses = []
    crashed = False

    for gen in range(N_GENERATIONS):
        if gen < WARMUP_STATIC:
            x_star = X_STAR_0
        else:
            x_star = X_STAR_0 + peak_v * (gen - WARMUP_STATIC)

        phenos = genes + rng.normal(0, SIGMA_E, N_POP)
        fits = fitness(phenos, x_star)
        fit_sum = float(fits.sum())

        if fit_sum < 1e-10:
            crashed = True
            for g2 in range(gen, N_GENERATIONS):
                if g2 >= WARMUP_STATIC + WARMUP_TRACK:
                    mean_fitnesses.append(0.0)
            break

        probs = fits / fit_sum
        sel_idx = rng.choice(N_POP, size=N_POP, p=probs)
        parent_genes = genes[sel_idx]
        mu = float(np.mean(genes))
        genes = mu + BETA * (parent_genes - mu) + rng.normal(0, SIGMA_V, N_POP)

        if gen >= WARMUP_STATIC + WARMUP_TRACK:
            mu_new = float(np.mean(genes))
            lag = x_star - mu_new
            lags.append(lag)
            mean_fitnesses.append(float(np.mean(fits)))

    mean_fit = float(np.mean(mean_fitnesses)) if mean_fitnesses else 0.0
    if crashed:
        return float('nan'), float('nan'), mean_fit
    mean_lag = float(np.mean(lags)) if lags else 0.0
    std_lag = float(np.std(lags)) if lags else 0.0
    return mean_lag, std_lag, mean_fit


def main():
    bar(f"{PID}  让峰开始移动------lag load定量")
    print(f"模型: x=g+e, g'=μ+β(g_sel-μ)+v_mut(回归到种群均值μ,非固定TARGET)")
    print(f"选择机制: 高斯加权(按fitness加权抽样,非截尾)")
    print(f"变化: fitness峰x*(t)=X_STAR_0+peak_v·gen(峰开始移动)")
    print(f"参数: β={BETA}, σ_e={SIGMA_E}, σ_v={SIGMA_V}, N={N_POP}, seeds={N_SEEDS}")
    print(f"fitness峰: x*_0={X_STAR_0}, ω={FITNESS_WIDTH}")
    print(f"理论: 等时滞后lag_eq=v/(β·h²·K),测量滞后lag*=v·(1−β·h²·K)/(β·h²·K)")
    print(f"      h²、K ← 186-1自洽Var(g)*(σ_v={SIGMA_V}固定)")
    print(f"      因子(1−β·h²·K)是测量口径因子(代码测x*(gen)−μ(gen+1),少一步v)")
    print(f"数值: gen={N_GENERATIONS}, 静止warmup={WARMUP_STATIC}, 跟踪warmup={WARMUP_TRACK}")
    print()

    _, _, h2, K, track_rate = theory_lag(1.0)
    sub("理论参数(σ_v=0.02自洽)")
    print(f"  h²* = {h2:.4f}")
    print(f"  K   = {K:.4f}")
    print(f"  β·h²·K = {track_rate:.6f}(每代跟踪速率)")
    print(f"  1−β·h²·K = {1.0 - track_rate:.6f}(测量口径因子)")
    print(f"  等时斜率 1/(β·h²·K) = {1.0 / track_rate:.2f}")
    print(f"  测量斜率 (1−β·h²·K)/(β·h²·K) = {(1.0 - track_rate) / track_rate:.2f}")
    print()

    sub("lag(v)曲线:理论 vs 数值")
    print(f"{'peak_v':>8s}  {'lag*理论':>10s}  {'lag数值':>10s}  {'lag std':>10s}  {'负荷理论':>10s}  {'平均fitness':>12s}  {'状态':>8s}")
    print("-" * 72)

    results = []
    for peak_v in PEAK_VELOCITIES:
        lag_th, loss_th, _, _, _ = theory_lag(peak_v)

        lags_seed = []
        fits_seed = []
        for seed in range(N_SEEDS):
            ml, sl, mf = run_one(peak_v, seed)
            lags_seed.append(ml)
            fits_seed.append(mf)

        valid_lags = [x for x in lags_seed if not math.isnan(x)]
        if valid_lags:
            lag_num = float(np.mean(valid_lags))
            lag_std = float(np.std(valid_lags))
        else:
            lag_num = float('nan')
            lag_std = float('nan')
        mean_fit = float(np.mean(fits_seed))

        if peak_v == 0.0:
            status = "基准"
        elif math.isnan(lag_num):
            status = "丢失"
        elif mean_fit < 0.001:
            status = "fit崩溃"
        elif lag_std / max(abs(lag_num), 1e-10) < 0.3:
            status = "跟踪"
        else:
            status = "过渡"

        results.append({
            'peak_v': peak_v, 'lag_theory': lag_th, 'lag_num': lag_num,
            'lag_std': lag_std, 'loss_theory': loss_th, 'mean_fit': mean_fit,
            'status': status,
        })

        if math.isnan(lag_num):
            lag_str = "       n/a"
            std_str = "       n/a"
        else:
            lag_str = f"{lag_num:>10.4f}"
            std_str = f"{lag_std:>10.4f}"
        print(f"{peak_v:>8.4f}  {lag_th:>10.4f}  {lag_str}  {std_str}  {loss_th:>10.6f}  {mean_fit:>12.6f}  {status:>8s}")

    print()

    sub("理论 vs 数值对比")
    for r in results:
        if r['peak_v'] == 0.0:
            continue
        if r['status'] in ("跟踪", "过渡", "fit崩溃"):
            ratio = r['lag_num'] / r['lag_theory'] if abs(r['lag_theory']) > 1e-10 else float('inf')
            print(f"  peak_v={r['peak_v']:.4f}: lag理论={r['lag_theory']:.4f} vs lag数值={r['lag_num']:.4f},比值={ratio:.2f}({r['status']})")
        else:
            print(f"  peak_v={r['peak_v']:.4f}: 理论lag={r['lag_theory']:.4f},种群丢失峰(fitness≈0)")

    print()

    sub("结论")
    print(f"186-2:fitness峰钉死x*=0.8,全链先验机器算N*(σ_v)")
    print(f"187-1:峰开始移动,lag*=v·(1−β·h²·K)/(β·h²·K)给出跟踪滞后定量")
    print(f"       跟踪速率 β·h²·K = {track_rate:.4f},测量斜率 = {(1.0 - track_rate) / track_rate:.1f}")
    track_vs = [r for r in results if r['status'] == "跟踪"]
    crash_vs = [r for r in results if r['status'] == "fit崩溃"]
    lost_vs = [r for r in results if r['status'] == "丢失"]
    if track_vs:
        print(f"       线性区:peak_v≤{track_vs[-1]['peak_v']:.4f},lag∝v,理论对得上")
    if crash_vs:
        print(f"       fit崩溃区:peak_v={crash_vs[0]['peak_v']:.4f},lag仍符合公式------崩溃正是理论的预言")
    if lost_vs:
        print(f"       丢失区:peak_v≥{lost_vs[0]['peak_v']:.4f},种群完全丢失峰,lag无良定义")
    print()
    print(f"  弧签名动作:186静止峰平衡 → 187移动峰追踪")


if __name__ == "__main__":
    main()

天赐范式 V3.3.25.0 · 2026-10-06

相关推荐
天赐范式1 天前
天赐范式第187天:让变异开始定价——动态环境下最优变异率
数字生命·复杂系统·天赐范式·动态运行时·最优变异率·bet-hedging·初始条件暂态
天赐范式2 天前
天赐范式第186天:让方差开始自洽——Bulmer效应的闭式验证
python·数字生命·天赐范式·动态运行时·遗传方差·bulmer效应
天赐范式3 天前
天赐范式第185天:让漂变开始定量——扫N看选择主导边界
python·信噪比·数字生命·天赐范式·动态运行时·种群大小·遗传漂变
天赐范式4 天前
天赐范式第183天:让平衡开始定量——收缩与选择的平衡点位置公式验证
数字生命·天赐范式·动态运行时·育种者方程·非线性归因·多seed验证·平衡位移
天赐范式5 天前
天赐范式第183天:让选择开始生效——育种者方程与选择生效条件
python·数字生命·天赐范式·动态运行时·育种者方程·选择压力·遗传力
天赐范式6 天前
天赐范式第181天:让视图开始切换——PBFT视图切换与从safety到liveness的跨越
python·pbft·数字生命·天赐范式·动态运行时·拜占庭容错
天赐范式7 天前
天赐范式第181天:让耦合开始失稳——竞争耦合与线性失稳边界
python·数字生命·天赐范式·lyapunov指数·动态运行时·耦合失稳·laplacian矩阵
天赐范式7 天前
天赐范式第182天:让变异开始存活——主线重启与变异存续条件
python·ar模型·数字生命·天赐范式·动态运行时·稳态方差·变异存续
天赐范式10 天前
天赐范式第175天:让活着的成员互相验证——异质互验与重放反伪造
python·数字生命·天赐范式·动态运行时·互验·重放反伪造