天赐范式第187天:让变异开始定价——动态环境下最优变异率

天赐范式第187天·第二篇:让变异开始定价------动态环境下最优变异率


摘要

扫σ_v×峰速双网格测平均fitness。动态环境(v>0)最优变异率σ_v*存在且随峰速增大(0.020→0.100),bet-hedging:环境变化率与变异率必须匹配。


一、接续187-1:峰动了,变异率有了双向作用

上一篇让峰开始移动,给出了lag*=v·(1−β·h²·K)/(β·h²·K)的跟踪滞后定量。这里有一个隐含的杠杆:lag*的分母里有h²*,而h²*由σ_v决定。

在静止环境里(183-1),变异率只有单向作用:σ_v越大→h²越大→选择越强,没有倒U,没有最优变异率。

峰一动,σ_v就有了双向作用:

  • σ_v太小 → 遗传方差不够 → h²低 → 跟踪速率βh²K低 → lag大 → fitness损失
  • σ_v太大 → Var(g)大 → 个体散布大 → 瞬时fitness掉

双向作用 → 应该有最优σ_v*。这就是bet-hedging的雏形:环境变化率与变异率必须匹配。


二、183-1的开放问题

183-1结论:加性模型下没有最优变异率------σ_v越大选择越强,倒U不出现,因为静止环境里变异纯受益。

这个结论在静止环境下成立。但直觉里那个倒U没错------缺了环境变化这个项。187-1把环境变化加进来了,187-2看倒U出不出现。

注意:187的模型与183不同。 183用固定TARGET=0.5,187回归到种群均值μ(187-1已说明)。所以v=0行不是严格复现183-1,而是新模型下的静止基准。


三、双网格实验设计

模型与187-1一致:g'=μ+β·(g_sel−μ)+v_mut,fitness峰x*(t)=x*_0+peak_v·gen。

固定:β=0.3, σ_e=0.02, N=200, seeds=20, gen=1000, 静止warmup=200, 跟踪warmup=200。

扫描:σ_v ∈ {0.005, 0.010, 0.020, 0.050, 0.100, 0.200} × peak_v ∈ {0, 0.001, 0.002, 0.003, 0.005, 0.010},36格点。测平均fitness(跟踪稳态后取均值)。


四、fitness(σ_v)曲线按峰速分组

σ_v\v 0.0000 0.0010 0.0020 0.0030 0.0050 0.0100
0.005 0.2423 0.0000 0.0000 0.0000 0.0000 0.0000
0.010 0.8861 0.0253 0.0000 0.0000 0.0000 0.0000
0.020 0.9566 0.6998 0.2773 0.0588 0.0004 0.0000
0.050 0.8707 0.8621 0.8369 0.7958 0.6778 0.3191
0.100 0.6898 0.6892 0.6872 0.6836 0.6722 0.6215
0.200 0.4408 0.4406 0.4405 0.4402 0.4390 0.4336

v=0列(静止峰): fitness在σ_v=0.020处达峰(0.957),两侧下降。低σ_v端(0.005)fitness=0.24------遗传方差太小,h²低→跟踪速率βh²K极小(τ≈1/(βh²K)≈1266代)→测量窗400代内仍在爬升途中。根因是初始条件暂态 :种群从μ₀=0.5出发、峰在0.8,弛豫未完成。高σ_v端(0.200)fitness=0.44------散布太大。静止环境下也有最优,但这是初始条件暂态(与N几乎无关,代数主导),不是环境驱动的。

v=0.001列(慢速峰): fitness在σ_v=0.050处达峰(0.862)。σ_v=0.020时fitness=0.70------lag=0.083带来fitness损失。σ_v=0.050时h²更高→跟踪更快→lag更小→fitness更高。

v=0.010列(快速峰): fitness在σ_v=0.100处达峰(0.621)。σ_v=0.050时fitness=0.32------峰太快,0.050的跟踪速率不够。σ_v=0.100时h²=0.96→跟踪速率最高→lag最小。

起点对照实验------证实初始条件暂态

把初始均值从μ₀=0.5(默认)挪到峰上μ₀=0.8,若低σ_v端fitness回升→证实根因是初始条件暂态而非N相关漂变:

σ_v μ₀=0.5(默认) μ₀=0.8(峰上) 差异
0.005 0.2334 0.9779 +0.7445
0.010 0.8677 0.9724 +0.1047
0.020 0.9564 0.9566 +0.0002
0.050 0.8709 0.8706 −0.0003

σ_v=0.005的0.24,只要把起点挪到峰上,立刻变成0.98。σ_v≥0.020两行起点无关(τ足够短,早收敛)。

代数扫描------与N无关,代数主导

固定σ_v=0.005、v=0,扫总代数×N。解析收敛值ω/√(ω²+σ_x²)=0.9793。

总代数 N=200 N=1000 N=5000
1000 0.2334 0.2474 0.2443
2000 0.4972 0.5007 0.4945
4000 0.7367 0.7377 0.7361
8000 0.8628 0.8634 0.8633

N三档几乎完全重合;代数从1000到8000,fitness从0.23爬到0.86,趋向解析收敛值0.979(τ≈1266代,8000代≈6.3τ时仍有残余暂态)。


五、最优σ_v* vs 峰速------bet-hedging

peak_v 最优σ_v* 最优fitness
0.0000 0.020 0.9566
0.0010 0.050 0.8621
0.0020 0.050 0.8369
0.0030 0.050 0.7958
0.0050 0.050 0.6778
0.0100 0.100 0.6215

最优σ_v*随峰速增大而增大:

  • v=0 → σ_v*=0.020(初始条件暂态vs散布)
  • v=0.001~0.005 → σ_v*=0.050(跟踪+暂态vs散布)
  • v=0.010 → σ_v*=0.100(快速峰需要更多方差来跟踪)

这就是bet-hedging:环境变化率与变异率必须匹配。 峰慢时少量变异够用,峰快时需要更多变异来维持跟踪能力。


六、结论与主线意义

问题 答案
动态环境下最优变异率存在吗? 存在 ✅。fitness对σ_v有内部峰值,双向作用(跟踪vs散布)
183-1"没有最优"还成立吗? 静止+无限代数成立;静止+有限代数有最优(初始条件暂态vs散布);动态有最优(跟踪vs散布)
最优σ_v*怎么随峰速变? v越大σ_v*越大(bet-hedging):0.050→0.100
对主线有什么用? 176变异池的"变异幅度该调多大"------第一次有环境侧的理论参照

叙事弧:

  • 183-1:静止环境无最优变异率
  • 187-1:峰开始移动,lag load定量
  • 187-2:动态环境最优变异率存在,σ_v*随峰速增大------bet-hedging
  • 弧签名动作:183静止环境无最优 → 187动态环境最优存在。
  • 主线意义:176变异池的"变异幅度该调多大" → 第一次有环境侧的理论参照。

降调:

  1. v=0行的最优是初始条件暂态效应。 低σ_v下h²低→跟踪速率βh²K极小(τ≈1/(βh²K)≈1266代)→测量窗400代内种群仍在从μ₀=0.5向峰0.8爬升途中,未达稳态。起点对照实验 :把μ₀挪到峰上0.8,σ_v=0.005的fitness从0.23立刻跳到0.98------证实根因是初始条件暂态。代数扫描:N三档(200/1000/5000)几乎完全重合(与N无关),代数从1000到8000fitness从0.23爬到0.86,趋向解析收敛值ω/√(ω²+σ_e²+Var(g)*)=0.979。无限代数下lag=0、fitness随σ_v单调降,无最优。这不是环境驱动的,是初始条件暂态。

  2. σ_v网格不够密。 最优σ_v*在0.050和0.100之间跳变(v=0.005→0.050,v=0.010→0.100),中间可能有过渡。加密σ_v网格(如0.060/0.070/0.080)能精确化边界。

  3. 模型与183不同。 183用固定TARGET,187回归到μ。v=0行不是严格复现183-1,而是新模型下的静止基准。模型变化在187-1已说明:环境动了,种群的"家"也跟着动。

  4. bet-hedging是定性结论。 "v越大σ_v*越大"的方向确立了,但σ_v*对v的定量关系(线性?幂律?)需要更多数据点。

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

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


附录:完整代码

python 复制代码
# -*- coding: utf-8 -*-
"""
天赐范式 第187天 第二篇
让变异开始定价------动态环境下最优变异率

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

接续187-1:峰移动后,变异率σ_v有了双向作用------
  σ_v太小→遗传方差不够→h²低→跟踪速率βh²K低→lag大→fitness损失
  σ_v太大→Var(g)大→个体散布大→瞬时fitness掉
预测:动态环境下平均fitness对σ_v出现峰值(最优变异率σ_v*)
      静止峰下无最优(复现183-1结论)
      峰速越快,最优σ_v*越大

模型(与187-1一致):g'=μ+β(g_sel-μ)+v_mut(回归到种群均值μ)
fitness峰移动:x*(t)=X_STAR_0+peak_v·gen
扫描:σ_v × peak_v 双网格
对照:起点在峰上(μ₀=0.8) vs 默认(μ₀=0.5) + 代数扫描验证初始条件暂态
"""

import sys
import math
import numpy as np

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

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

TARGET = 0.5
X_STAR_0 = 0.8
FITNESS_WIDTH = 0.10
BETA = 0.3
SIGMA_E = 0.02
N_POP = 200
N_GENERATIONS = 1000
WARMUP_STATIC = 200
WARMUP_TRACK = 200
N_SEEDS = 20

SIGMA_V_GRID = [0.005, 0.010, 0.020, 0.050, 0.100, 0.200]
PEAK_VELOCITIES = [0.0, 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(5000):
        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) < 1e-12:
            return var_g_new
        var_g = var_g_new
    return var_g


def run_one(sigma_v, peak_v, seed, start_mu=None, n_gen=None, n_pop=None):
    if start_mu is None:
        start_mu = TARGET
    if n_gen is None:
        n_gen = N_GENERATIONS
    if n_pop is None:
        n_pop = N_POP
    rng = np.random.RandomState(seed)
    genes = rng.normal(start_mu, 0.01, n_pop)
    fitnesses = []

    for gen in range(n_gen):
        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:
            for g2 in range(gen, n_gen):
                if g2 >= WARMUP_STATIC + WARMUP_TRACK:
                    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:
            fitnesses.append(float(np.mean(fits)))

    return float(np.mean(fitnesses)) if fitnesses else 0.0


def main():
    bar(f"{PID}  让变异开始定价------动态环境下最优变异率")
    print(f"模型: g'=μ+β(g_sel-μ)+v_mut(回归到种群均值μ)")
    print(f"选择机制: 高斯加权(按fitness加权抽样,非截尾)")
    print(f"fitness峰: x*(t)=X_STAR_0+peak_v·gen")
    print(f"参数: β={BETA}, σ_e={SIGMA_E}, N={N_POP}, seeds={N_SEEDS}")
    print(f"扫描: σ_v×peak_v双网格,测平均fitness(跟踪稳态后取均值)")
    print(f"预测: 静止峰(v=0)无最优σ_v;动峰(v>0)出现最优σ_v*;v越大σ_v*越大")
    print()

    sub("σ_v × peak_v 双网格:平均fitness")
    header = f"{'σ_v\v':>8s}" + "".join(f"{v:>10.4f}" for v in PEAK_VELOCITIES)
    print(header)
    print("-" * len(header))

    grid = np.zeros((len(SIGMA_V_GRID), len(PEAK_VELOCITIES)))
    for i, sigma_v in enumerate(SIGMA_V_GRID):
        row = []
        for j, peak_v in enumerate(PEAK_VELOCITIES):
            fits = []
            for seed in range(N_SEEDS):
                fits.append(run_one(sigma_v, peak_v, seed))
            mean_fit = float(np.mean(fits))
            grid[i, j] = mean_fit
            row.append(mean_fit)
        row_str = "".join(f"{f:>10.4f}" for f in row)
        print(f"{sigma_v:>8.3f}{row_str}")

    print()

    sub("各峰速下最优σ_v")
    print(f"{'peak_v':>8s}  {'最优σ_v':>10s}  {'最优fitness':>12s}")
    print("-" * 72)

    for j, peak_v in enumerate(PEAK_VELOCITIES):
        col = grid[:, j]
        best_idx = int(np.argmax(col))
        best_sv = SIGMA_V_GRID[best_idx]
        best_fit = col[best_idx]
        print(f"{peak_v:>8.4f}  {best_sv:>10.3f}  {best_fit:>12.6f}")

    print()

    sub("对照实验:起点在峰上 vs 默认起点(v=0静止峰)")
    print(f"低σ_v端fitness低,根因是初始条件暂态(μ₀=0.5→峰0.8的弛豫)")
    print(f"把起点挪到峰上(μ₀=0.8),若fitness回升→证实初始条件暂态")
    print()
    print(f"{'σ_v':>8s}  {'μ₀=0.5(默认)':>14s}  {'μ₀=0.8(峰上)':>14s}  {'差异':>10s}")
    print("-" * 72)
    for sv in [0.005, 0.010, 0.020, 0.050]:
        f_default = np.mean([run_one(sv, 0.0, s, start_mu=0.5) for s in range(3)])
        f_peak = np.mean([run_one(sv, 0.0, s, start_mu=0.8) for s in range(3)])
        print(f"{sv:>8.3f}  {f_default:>14.4f}  {f_peak:>14.4f}  {f_peak - f_default:>10.4f}")
    print()

    sub("代数扫描:σ_v=0.005, v=0(验证初始条件暂态 vs N依赖)")
    var_g_star = solve_self_consistent(0.005)
    sigma_x2 = var_g_star + SIGMA_E ** 2
    fit_analytic = FITNESS_WIDTH / math.sqrt(FITNESS_WIDTH ** 2 + sigma_x2)
    print(f"解析收敛值 ω/√(ω²+σ_x²) = {fit_analytic:.4f}")
    print()
    print(f"{'总代数':>8s}  {'N=200':>10s}  {'N=1000':>10s}  {'N=5000':>10s}")
    print("-" * 72)
    for n_gen in [1000, 2000, 4000, 8000]:
        row = []
        for n_pop in [200, 1000, 5000]:
            f = np.mean([run_one(0.005, 0.0, s, n_gen=n_gen, n_pop=n_pop) for s in range(3)])
            row.append(f)
        print(f"{n_gen:>8d}  {row[0]:>10.4f}  {row[1]:>10.4f}  {row[2]:>10.4f}")
    print()

    sub("结论")
    print(f"183-1:静止环境加性模型无最优变异率(σ_v越大选择越强,倒U不出现)")
    v0_col = grid[:, 0]
    v0_best = int(np.argmax(v0_col))
    if v0_best == 0:
        print(f"       v=0行复现:fitness随σ_v单调降,最优在σ_v→0,无内部峰值 ✅")
    else:
        print(f"       v=0行:最优σ_v={SIGMA_V_GRID[v0_best]:.3f}(初始条件暂态效应,非稳态)")

    has_peak = any(0 < int(np.argmax(grid[:, j])) < len(SIGMA_V_GRID) - 1
                   for j in range(1, len(PEAK_VELOCITIES)))
    if has_peak:
        print(f"187-2:动态环境出现最优变异率σ_v* ✅")
        for j in range(1, len(PEAK_VELOCITIES)):
            peak_v = PEAK_VELOCITIES[j]
            best_idx = int(np.argmax(grid[:, j]))
            best_sv = SIGMA_V_GRID[best_idx]
            print(f"       peak_v={peak_v:.4f} → 最优σ_v*={best_sv:.3f}")
    else:
        print(f"187-2:动态环境未出现明显峰值(可能网格不够密或参数区不对)")

    print()
    print(f"  弧签名动作:183静止环境无最优 → 187动态环境最优存在")
    print(f"  主线意义:176变异池的'变异幅度该调多大'------第一次有环境侧的理论参照")


if __name__ == "__main__":
    main()

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

相关推荐
天赐范式14 小时前
天赐范式第186天:让方差开始自洽——Bulmer效应的闭式验证
python·数字生命·天赐范式·动态运行时·遗传方差·bulmer效应
天赐范式2 天前
天赐范式第185天:让漂变开始定量——扫N看选择主导边界
python·信噪比·数字生命·天赐范式·动态运行时·种群大小·遗传漂变
天赐范式3 天前
天赐范式第183天:让平衡开始定量——收缩与选择的平衡点位置公式验证
数字生命·天赐范式·动态运行时·育种者方程·非线性归因·多seed验证·平衡位移
天赐范式4 天前
天赐范式第183天:让选择开始生效——育种者方程与选择生效条件
python·数字生命·天赐范式·动态运行时·育种者方程·选择压力·遗传力
天赐范式5 天前
天赐范式第181天:让视图开始切换——PBFT视图切换与从safety到liveness的跨越
python·pbft·数字生命·天赐范式·动态运行时·拜占庭容错
天赐范式6 天前
天赐范式第181天:让耦合开始失稳——竞争耦合与线性失稳边界
python·数字生命·天赐范式·lyapunov指数·动态运行时·耦合失稳·laplacian矩阵
天赐范式6 天前
天赐范式第182天:让变异开始存活——主线重启与变异存续条件
python·ar模型·数字生命·天赐范式·动态运行时·稳态方差·变异存续
天赐范式9 天前
天赐范式第175天:让活着的成员互相验证——异质互验与重放反伪造
python·数字生命·天赐范式·动态运行时·互验·重放反伪造
天赐范式17 天前
天赐范式第165天:让理开始生根——第一性原理:双层架构是稳定学习系统的必然收敛解
天赐范式·动态运行时·必然≠唯一·收敛≠终点·稳定≠永恒·同态≠同构·必要条件≠充分条件