天赐范式第183天第二篇:让平衡开始定量------收缩与选择的平衡点位置公式验证
版本 V3.3.21.0 | PID: TC-183B-V3.3.21.0 | 2026-10-02
摘要
多seed CI+β扫描+非线性归因三项验证Δ*=β·h²·S/(1-β):20个seed比值mean≈1.00(σ_v≥0.005)公式无系统偏差,单seed偏高是漂变非偏差。
一、接续183-1------从单seed到多seed
183-1用单seed验证了Δ*=β·h²·S/(1-β)。中间段(σ_v=0.0050.200)比值1.021.05,公式成立。但单seed有漂变噪声------多seed下公式还成立吗?大σ_v时单seed比值偏高1.04~1.16------系统偏差还是随机漂变?
183-2做三件事:
- 多seed CI:20个seed报比值mean±std,确认公式非偶然
- β扫描:固定σ_v=0.05,扫β=0.1~0.9,确认公式跨收缩强度成立
- 非线性归因:线性fitness vs 高斯fitness对照,大σ_v单seed比值偏高归因fitness非线性
二、多seed CI扫描------20个seed报比值稳定性
200个个体,500代,β=0.3,σ_e=0.02,选择比例0.3,20个seed。(口径:每个seed独立算比值再取mean±std)
| σ_v | 比值mean | 比值std | +1σ下界 | +1σ上界 | n_valid |
|---|---|---|---|---|---|
| 0.001 | 0.9791 | 0.2147 | 0.7644 | 1.1938 | 20 |
| 0.005 | 1.0062 | 0.0461 | 0.9601 | 1.0523 | 20 |
| 0.010 | 1.0037 | 0.0223 | 0.9815 | 1.0260 | 20 |
| 0.020 | 1.0051 | 0.0139 | 0.9912 | 1.0190 | 20 |
| 0.050 | 1.0027 | 0.0110 | 0.9917 | 1.0137 | 20 |
| 0.100 | 1.0008 | 0.0110 | 0.9898 | 1.0118 | 20 |
| 0.200 | 1.0003 | 0.0129 | 0.9874 | 1.0132 | 20 |
| 0.400 | 0.9999 | 0.0241 | 0.9758 | 1.0240 | 20 |
| 0.800 | 1.0001 | 0.0468 | 0.9533 | 1.0469 | 20 |
| 1.500 | 1.0051 | 0.0867 | 0.9185 | 1.0918 | 20 |
→ 所有σ_v(除0.001)比值mean≈1.00,公式无系统偏差------183-1单seed偏高是漂变。
- std随σ_v增大:大σ_v单seed波动大,但多seed均值稳定在1.0
- 小σ_v(0.001)比值波动大------Δ和理论都接近0,比值不稳定但无意义
- σ_v=0.001的CI=0.7644,1.1938跨过1.0:因Δ和理论都接近0,比值由噪声主导,不具统计意义
- 大σ_v单seed偏高经6seed窗口后移测试确认为漂变(见降调8)
三、β扫描------固定σ_v=0.05,扫β=0.1~0.9
固定σ_v=0.05(h²≈0.86,选择生效区),扫β验证公式跨收缩强度成立。每个β跑5个seed取均值(5个而非20个,计算成本考量:9个β点×20个seed=180次演化,5个seed=45次)。(口径:先取Δ和theory的跨seed均值,再算均值比值------与第二节不同)
| β | h²(力) | S(差) | Δ(实测) | β·h²·S/(1-β) | 比值 |
|---|---|---|---|---|---|
| 0.1 | 0.8608 | +0.062217 | +0.005977 | +0.00595055 | 1.0045 |
| 0.2 | 0.8621 | +0.062499 | +0.013521 | +0.01346936 | 1.0038 |
| 0.3 | 0.8642 | +0.063006 | +0.023459 | +0.02333587 | 1.0053 |
| 0.4 | 0.8672 | +0.063739 | +0.036970 | +0.03684777 | 1.0033 |
| 0.5 | 0.8711 | +0.064759 | +0.056603 | +0.05641311 | 1.0034 |
| 0.6 | 0.8759 | +0.066048 | +0.087196 | +0.08677796 | 1.0048 |
| 0.7 | 0.8820 | +0.067805 | +0.140120 | +0.13953996 | 1.0042 |
| 0.8 | 0.8821 | +0.062227 | +0.220373 | +0.21956398 | 1.0037 |
| 0.9 | 0.8780 | +0.033419 | +0.263919 | +0.26406464 | 0.9994 |
→ 所有β下比值≈1.00,公式跨收缩强度成立。大β(≥0.7)时Δ大(收缩弱,选择位移大),但比值仍稳定。β=0.9时S从约0.064降到0.033:均值逼近fitness峰0.8,选择梯度自然减弱。
四、非线性归因------线性fitness vs 高斯fitness对照
大σ_v时单seed比值偏高:是fitness非线性导致还是模型错误?
对照实验:
- 高斯fitness: exp(-(x-0.8)²/(2·0.1²))(非线性,183-1用的)
- 线性fitness: x(线性,选择差直接正比于表型)
| σ_v | 高斯比值 | 线性比值 | 归因 |
|---|---|---|---|
| 0.050 | 1.0214 | 1.0214 | 都好(线性区) |
| 0.200 | 1.0222 | 1.0184 | 都好(线性区) |
| 0.400 | 1.0417 | 1.0184 | 高斯非线性致偏高 |
| 0.800 | 1.0821 | 1.0184 | 高斯非线性致偏高 |
| 1.500 | 1.1612 | 1.0183 | 高斯非线性致偏高 |
→ 线性fitness单seed比值稳定≈1.02:非线性弱,漂变小。高斯fitness单seed比值随σ_v增大:非线性强,放大单seed漂变。
初步归因:大σ_v单seed比值偏高是fitness非线性放大漂变,多seed均值仍≈1.0(见第二节)。单seed对照未做多seed验证。
五、降调声明
- 本篇是demo演示。公式从更新规则严格推导(见183-1第三节),按147-2实测定义demo是模拟不是实证。
- 多seed CI用±1σ(20个seed),非严格95%置信区间------seed数有限,目的是报稳定性非统计推断。
- β扫描固定σ_v=0.05,不同σ_v下β扫描结果可能不同------这里验证一个代表点。
- 线性fitness=x无上界,实际fitness应有上界------这里用作非线性归因的对照,不是实际模型。
- 非线性归因只做了单seed对照,多seed下结论应一致但未验证。
- 与183-1降调一致:fitness是设定的、无重组无交配、有限种群有漂变。
- 本验证本质是自洽性检查:公式Δ*=β·h²·S/(1-β)是平均更新规则的不动点,S和h²都从同一模拟测出,ratio≈1构造上注定。这不是独立预测------要让公式有预测力,需让S由适应度景观独立算出而非从模拟测。
- 大σ_v偏高归因经6seed窗口后移测试验证:窗口起点100/200/300/500,窗长400,跨seed均值偏差均<1 SE(0.68/0.75/0.85σ),慢暂态假说未复现,维持漂变归因。测试代码见下方附录(窗口后移三方判决测试代码)。
- 育种者方程Δ*=β·h²·S/(1-β)是Lush(1937)标准结果。本篇贡献是验证其在多seed下的稳定性,不是发现新公式。
六、七条前提条件------平衡位移定量验证
- 条件1 独立性 ✅ 每个体独立变异独立被选
- 条件2 隐私性 ✅ 纯数学验证,不涉及隐私
- 条件3 繁衍性 🟡 种群代际循环是繁衍的简化模型,非完整繁衍验证
- 条件4 安全性 ✅ β有界,种群有界
- 条件5 不可篡改 --- 本demo不涉及篡改场景
- 条件6 可继承 🟡 育种者方程可移植,非系列定义的基因跨代传递
- 条件7 可终止 ✅ 有限代终止(数学语境映射,非体系达标)
结语
183-2接续183-1,对Δ*=β·h²·S/(1-β)做定量验证。
三项验证结果:
- 多seed CI:所有σ_v(σ_v≥0.005)比值mean≈1.00,公式无系统偏差
- β扫描:所有β下比值≈1.00,公式跨收缩强度成立
- 非线性归因:高斯fitness放大单seed漂变,线性fitness漂变小------非模型错误
公式Δ*=β·h²·S/(1-β)在多seed下无系统偏差,单seed偏差是漂变------如实报。
183-1给公式,183-2验公式。多seed下比值mean约1.00无系统偏差,单seed偏高是漂变------公式站住。
这个系列还在逐步建设中,完善也是咱们和伙伴们的努力方向。

代码附录
python
# -*- coding: utf-8 -*-
"""
天赐范式第183天第二篇:让平衡开始定量 V3.3.21.0
接续183-1,对Delta*=beta*h^2*S/(1-beta)做多seed CI + beta扫描 + 非线性归因验证
模型(同183-1):
表型 x = g + e, e ~ N(0, sigma_e^2)
子代基因 g' = TARGET + beta*(g_sel - TARGET) + v, v ~ N(0, sigma_v^2)
Delta* = beta * h^2 * S / (1 - beta)
三项验证:
1. 多seed CI:20个seed报比值mean+-std,确认公式非偶然
2. beta扫描:固定sigma_v=0.05,扫beta=0.1~0.9,确认公式跨收缩强度成立
3. 非线性归因:线性fitness vs 高斯fitness对照,大sigma_v比值偏高归因fitness非线性
"""
import sys
import random
import math
import numpy as np
if hasattr(sys.stdout, 'reconfigure'):
sys.stdout.reconfigure(encoding='utf-8')
PID = "TC-183B-V3.3.21.0"
TARGET = 0.5
FITNESS_PEAK = 0.8
BETA = 0.3
SIGMA_E = 0.02
N_POP = 200
N_GENERATIONS = 500
SELECT_FRAC = 0.3
N_SEEDS = 20
SIGMA_GRID = [0.001, 0.005, 0.01, 0.02, 0.05, 0.10, 0.20, 0.40, 0.80, 1.50]
BETA_GRID = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
def bar(title):
print("=" * 72)
print(" " + title)
print("=" * 72)
print()
def sub(title):
print("【" + title)
print("-" * 72)
def fitness(x, mode='gauss', width=0.10):
if mode == 'linear':
return x
return math.exp(-(x - FITNESS_PEAK) ** 2 / (2 * width ** 2))
def run_generation(genes, sigma_v, sigma_e, beta, rng, mode='gauss', width=0.10):
phenos = [g + rng.gauss(0, sigma_e) for g in genes]
n_select = max(2, int(len(genes) * SELECT_FRAC))
fits = [fitness(x, mode=mode, width=width) for x in phenos]
ranked = sorted(range(len(genes)), key=lambda i: fits[i], reverse=True)
selected_idx = ranked[:n_select]
mean_parents_x = float(np.mean(phenos))
mean_selected_x = float(np.mean([phenos[i] for i in selected_idx]))
S = mean_selected_x - mean_parents_x
offspring = []
for _ in range(len(genes)):
parent_g = genes[rng.choice(selected_idx)]
child_g = TARGET + beta * (parent_g - TARGET) + rng.gauss(0, sigma_v)
offspring.append(child_g)
mean_offspring_x = float(np.mean(offspring))
var_g = float(np.var(genes))
h2 = var_g / (var_g + sigma_e ** 2) if (var_g + sigma_e ** 2) > 1e-15 else 0.0
return offspring, S, h2, mean_offspring_x, var_g
def run_evolution(sigma_v, n_pop, n_gen, beta, sigma_e, seed=42,
mode='gauss', width=0.10, warmup=100):
rng = random.Random(seed)
genes = [TARGET + rng.gauss(0, 0.1) for _ in range(n_pop)]
Ss, h2s, means_x = [], [], []
for gen in range(n_gen):
genes, S, h2, mean_x, var_g = run_generation(
genes, sigma_v, sigma_e, beta, rng, mode=mode, width=width)
if gen >= warmup:
Ss.append(S)
h2s.append(h2)
means_x.append(mean_x)
return {
'S_mean': float(np.mean(Ss)),
'h2_mean': float(np.mean(h2s)),
'mean_stable': float(np.mean(means_x)),
}
def main():
bar("天赐范式第183天第二篇:让平衡开始定量 V3.3.21.0")
print(" PID: {}".format(PID))
print()
sub("步骤0】接续183-1------从单seed到多seed")
print(" 183-1用单seed验证了Delta* = beta * h^2 * S / (1 - beta)。")
print(" 中间段(sigma_v=0.005~0.200)比值1.02~1.05,公式成立。")
print(" 但单seed有漂变噪声------多seed下公式还成立吗?")
print(" 大sigma_v时比值偏高1.04~1.16------系统偏差还是随机漂变?")
print()
print(" 183-2做三件事:")
print(" (1) 多seed CI:20个seed报比值mean+-std,确认公式非偶然")
print(" (2) beta扫描:固定sigma_v=0.05,扫beta=0.1~0.9,确认公式跨收缩强度成立")
print(" (3) 非线性归因:线性fitness vs 高斯fitness对照,大sigma_v比值偏高归因fitness非线性")
print()
sub("步骤1】多seed CI扫描------20个seed报比值稳定性")
print(" {}个个体,{}代,beta={},sigma_e={},选择比例{},{}个seed".format(
N_POP, N_GENERATIONS, BETA, SIGMA_E, SELECT_FRAC, N_SEEDS))
print(" (口径:每个seed独立算比值再取mean+-std)")
print()
print(" | sigma_v | 比值mean | 比值std | +1σ下界 | +1σ上界 | n_valid |")
print(" |---------|----------|----------|---------|---------|---------|")
for sigma_v in SIGMA_GRID:
ratios = []
for seed in range(N_SEEDS):
res = run_evolution(sigma_v, N_POP, N_GENERATIONS, BETA, SIGMA_E, seed=seed)
delta = res['mean_stable'] - TARGET
delta_theory = BETA * res['h2_mean'] * res['S_mean'] / (1 - BETA)
if abs(delta_theory) > 1e-8:
ratios.append(delta / delta_theory)
if len(ratios) > 0:
r_mean = float(np.mean(ratios))
r_std = float(np.std(ratios))
ci_lo = r_mean - r_std
ci_hi = r_mean + r_std
print(" | {:.3f} | {:8.4f} | {:8.4f} | {:7.4f} | {:7.4f} | {:7d} |".format(
sigma_v, r_mean, r_std, ci_lo, ci_hi, len(ratios)))
print()
print(" -> 所有sigma_v(除0.001)比值mean约1.00,公式无系统偏差------183-1单seed偏高是漂变")
print(" -> std随sigma_v增大:大sigma_v单seed波动大,但多seed均值稳定在1.0")
print(" -> 小sigma_v(0.001)比值波动大------Delta和理论都接近0,比值不稳定但无意义")
print(" -> sigma_v=0.001的CI=[0.7644,1.1938]跨过1.0:因Delta和理论都接近0,")
print(" 比值由噪声主导,不具统计意义")
print(" -> 大sigma_v单seed偏高经6seed窗口后移测试确认为漂变(见降调8)")
print()
sub("步骤2】beta扫描------固定sigma_v=0.05,扫beta=0.1~0.9")
print(" 固定sigma_v=0.05(h^2约0.86,选择生效区),扫beta验证公式跨收缩强度成立")
print(" 每个beta跑5个seed取均值(5个而非20个,计算成本考量:")
print(" 9个beta点x20个seed=180次演化,5个seed=45次)")
print(" (口径:先取Delta和theory的跨seed均值,再算均值比值------与步骤1不同)")
print()
print(" | beta | h^2(力) | S(差) | Delta(实测) | b*h2*S/(1-b) | 比值 |")
print(" |------|---------|---------|------------|--------------|--------|")
for beta_val in BETA_GRID:
deltas, deltas_theory = [], []
h2s, Ss = [], []
for seed in range(5):
res = run_evolution(0.05, N_POP, N_GENERATIONS, beta_val, SIGMA_E, seed=seed)
delta = res['mean_stable'] - TARGET
delta_theory = beta_val * res['h2_mean'] * res['S_mean'] / (1 - beta_val)
deltas.append(delta)
deltas_theory.append(delta_theory)
h2s.append(res['h2_mean'])
Ss.append(res['S_mean'])
d_mean = float(np.mean(deltas))
dt_mean = float(np.mean(deltas_theory))
h2_mean = float(np.mean(h2s))
S_mean = float(np.mean(Ss))
ratio = d_mean / dt_mean if abs(dt_mean) > 1e-8 else 0
print(" | {:.1f} | {:.4f} | {:+.6f}| {:+.6f} | {:+.8f} | {:6.4f} |".format(
beta_val, h2_mean, S_mean, d_mean, dt_mean, ratio))
print()
print(" -> 所有beta下比值约1.00,公式跨收缩强度成立")
print(" -> 大beta(>=0.7)时Delta大(收缩弱,选择位移大),但比值仍稳定")
print(" -> beta=0.9时S从约0.064降到0.033:均值逼近fitness峰0.8,选择梯度自然减弱")
print()
sub("步骤3】非线性归因------线性fitness vs 高斯fitness对照")
print(" 大sigma_v时比值偏高:是fitness非线性导致还是模型错误?")
print(" 对照实验:")
print(" 高斯fitness: exp(-(x-0.8)^2/(2*0.1^2))(非线性,183-1用的)")
print(" 线性fitness: x(线性,选择差直接正比于表型)")
print(" 预期:线性fitness下比值约1.0(线性回归精确),高斯下大sigma_v比值>1.0")
print()
print(" | sigma_v | 高斯比值 | 线性比值 | 归因 |")
print(" |---------|----------|----------|--------------------|")
test_sigmas = [0.05, 0.20, 0.40, 0.80, 1.50]
for sigma_v in test_sigmas:
res_g = run_evolution(sigma_v, N_POP, N_GENERATIONS, BETA, SIGMA_E,
seed=42, mode='gauss')
res_l = run_evolution(sigma_v, N_POP, N_GENERATIONS, BETA, SIGMA_E,
seed=42, mode='linear')
d_g = res_g['mean_stable'] - TARGET
dt_g = BETA * res_g['h2_mean'] * res_g['S_mean'] / (1 - BETA)
ratio_g = d_g / dt_g if abs(dt_g) > 1e-8 else 0
d_l = res_l['mean_stable'] - TARGET
dt_l = BETA * res_l['h2_mean'] * res_l['S_mean'] / (1 - BETA)
ratio_l = d_l / dt_l if abs(dt_l) > 1e-8 else 0
if sigma_v <= 0.20:
attribution = "都好(线性区)"
else:
attribution = "高斯非线性致偏高" if ratio_g > 1.03 else "都好"
print(" | {:.3f} | {:8.4f} | {:8.4f} | {} |".format(
sigma_v, ratio_g, ratio_l, attribution))
print()
print(" -> 线性fitness单seed比值稳定约1.02:非线性弱,漂变小")
print(" -> 高斯fitness单seed比值随sigma_v增大:非线性强,放大单seed漂变")
print(" -> 初步归因:大sigma_v单seed比值偏高是fitness非线性放大漂变,")
print(" 多seed均值仍约1.0(见步骤1)。单seed对照未做多seed验证。")
print()
sub("步骤4】降调声明")
print(" 1. 本篇是demo演示。公式从更新规则严格推导(见183-1步骤2),按147-2实测定义demo是模拟不是实证。")
print(" 2. 多seed CI用+-1sigma(20个seed),非严格95%置信区间------seed数有限,目的是报稳定性非统计推断。")
print(" 3. beta扫描固定sigma_v=0.05,不同sigma_v下beta扫描结果可能不同------这里验证一个代表点。")
print(" 4. 线性fitness=x无上界,实际fitness应有上界------这里用作非线性归因的对照,不是实际模型。")
print(" 5. 非线性归因只做了单seed对照,多seed下结论应一致但未验证。")
print(" 6. 与183-1降调一致:fitness是设定的、无重组无交配、有限种群有漂变。")
print(" 7. 本验证本质是自洽性检查:公式Delta*=beta*h^2*S/(1-beta)是平均更新规则的不动点,")
print(" S和h^2都从同一模拟测出,ratio约1构造上注定。这不是独立预测------")
print(" 要让公式有预测力,需让S由适应度景观独立算出而非从模拟测。")
print(" 8. 大sigma_v偏高归因经6seed窗口后移测试验证:")
print(" 窗口起点100/200/300/500,窗长400,跨seed均值偏差均<1 SE")
print(" (0.68/0.75/0.85 sigma),慢暂态假说未复现,维持漂变归因。")
print(" 测试代码见下方附录(窗口后移三方判决测试代码)。")
print(" 9. 育种者方程Delta*=beta*h^2*S/(1-beta)是Lush(1937)标准结果。")
print(" 本篇贡献是验证其在多seed下的稳定性,不是发现新公式。")
print()
sub("步骤5】七条前提条件------平衡位移定量验证")
print(" 条件1 独立性 ✅ 每个体独立变异独立被选")
print(" 条件2 隐私性 ✅ 纯数学验证,不涉及隐私")
print(" 条件3 繁衍性 🟡 种群代际循环是繁衍的简化模型,非完整繁衍验证")
print(" 条件4 安全性 ✅ beta有界,种群有界")
print(" 条件5 不可篡改 --- 本demo不涉及篡改场景")
print(" 条件6 可继承 🟡 育种者方程可移植,非系列定义的基因跨代传递")
print(" 条件7 可终止 ✅ 有限代终止(数学语境映射,非体系达标)")
print()
bar("结语")
print(" 183-2接续183-1,对Delta* = beta * h^2 * S / (1 - beta)做定量验证。")
print()
print(" 三项验证结果:")
print(" (1) 多seed CI:所有sigma_v(sigma_v>=0.005)比值mean约1.00,公式无系统偏差")
print(" (2) beta扫描:所有beta下比值约1.00,公式跨收缩强度成立")
print(" (3) 非线性归因:高斯fitness放大单seed漂变,线性fitness漂变小------非模型错误")
print()
print(" 公式Delta*=beta*h^2*S/(1-beta)在多seed下无系统偏差,单seed偏差是漂变------如实报。")
print()
print(" 183-1给公式,183-2验公式。多seed下比值mean约1.00无系统偏差,单seed偏高是漂变------公式站住。")
print()
print(" 这个系列还在逐步建设中,完善也是咱们和伙伴们的努力方向。")
print("=" * 72)
if __name__ == "__main__":
main()

附录:窗口后移三方判决测试
大σ_v单seed比值偏高的归因,伙伴独立验证提出"慢暂态/窗口敏感"假说。本篇对此做了三方判决测试,预登记判据先写死再跑数。
三个假说对窗口后移的预测:
| 假说 | 窗口后移时比值行为 |
|---|---|
| 慢暂态 | 单调向1收敛 |
| Jensen/协方差系统偏差 | 稳定偏离1,不随窗口动 |
| 纯漂变 | 单seed附近随机游走,无趋势 |
测试设计:seed=42+seed 0--4,σ_v∈{0.40,0.80,1.50},窗口起点100/200/300/500,窗长400,总代数900。
跨6个seed均值序列(核心判决表):
| σ_v | w=100 | w=200 | w=300 | w=500 | 偏差/SE |
|---|---|---|---|---|---|
| 0.40 | 1.0067 | 1.0044 | 0.9993 | 1.0059 | 0.68σ |
| 0.80 | 1.0146 | 1.0093 | 0.9996 | 1.0095 | 0.75σ |
| 1.50 | 1.0299 | 1.0205 | 0.9986 | 1.0138 | 0.85σ |
判决结果:
- 慢暂态❌:w300→w500三个σ_v全反弹,单调收敛假说不允许反弹;6个seed只有2个呈收敛趋势,伙伴看到的是cherry-pick
- 系统偏差❌:w300跨seed均值全回到≈1.0(0.9993/0.9996/0.9986),不是稳定偏离
- 纯漂变✅:所有偏差<1 SE(0.68/0.75/0.85σ),统计不显著
论证顺序:偏差<1 SE是决定性证据(跨seed均值的直接统计陈述),非单调作为辅助(四个窗口共享数据段,估计值高度相关,非单调性证据强度打折)。
结论:维持漂变归因,慢暂态未复现。β=0.3时warmup=100是70+个时间常数,暂态理论上早死透。测试脚本tianci_183_window_test.py及完整输出window_test_output.txt随文留档。
窗口后移三方判决测试代码
python
# -*- coding: utf-8 -*-
"""
天赐范式第183天:窗口后移三方判决测试
预登记判据 -> 跑数 -> 判归属
三个假说对窗口后移的预测各不相同:
慢暂态 : 比值随窗口起点单调向1收敛
系统偏差(Jensen): 稳定偏离1,不随窗口动
纯漂变 : 单seed值附近随机游走,无趋势
测试设计(预登记):
复现基点 : seed=42 + seed 0-4
取点 : sigma_v in {0.40, 0.80, 1.50}
窗口起点 : 100 / 200 / 300 / 500
窗长 : 400
总代数 : 900 (500 + 400)
"""
import sys
import random
import math
import numpy as np
if hasattr(sys.stdout, 'reconfigure'):
sys.stdout.reconfigure(encoding='utf-8')
PID = "TC-183-WINDOW-TEST"
TARGET = 0.5
FITNESS_PEAK = 0.8
BETA = 0.3
SIGMA_E = 0.02
N_POP = 200
SELECT_FRAC = 0.3
TEST_SIGMAS = [0.40, 0.80, 1.50]
TEST_SEEDS = [42, 0, 1, 2, 3, 4]
WINDOW_STARTS = [100, 200, 300, 500]
WINDOW_LEN = 400
N_TOTAL_GEN = 900
def bar(title):
print("=" * 78)
print(" " + title)
print("=" * 78)
print()
def sub(title):
print("【" + title)
print("-" * 78)
def fitness(x, mode='gauss', width=0.10):
if mode == 'linear':
return x
return math.exp(-(x - FITNESS_PEAK) ** 2 / (2 * width ** 2))
def run_generation_record(genes, sigma_v, sigma_e, beta, rng,
mode='gauss', width=0.10):
phenos = [g + rng.gauss(0, sigma_e) for g in genes]
n_select = max(2, int(len(genes) * SELECT_FRAC))
fits = [fitness(x, mode=mode, width=width) for x in phenos]
ranked = sorted(range(len(genes)), key=lambda i: fits[i], reverse=True)
selected_idx = ranked[:n_select]
mean_parents_x = float(np.mean(phenos))
mean_selected_x = float(np.mean([phenos[i] for i in selected_idx]))
S = mean_selected_x - mean_parents_x
offspring = []
for _ in range(len(genes)):
parent_g = genes[rng.choice(selected_idx)]
child_g = TARGET + beta * (parent_g - TARGET) + rng.gauss(0, sigma_v)
offspring.append(child_g)
mean_offspring_x = float(np.mean(offspring))
var_g = float(np.var(genes))
h2 = var_g / (var_g + sigma_e ** 2) if (var_g + sigma_e ** 2) > 1e-15 else 0.0
return offspring, S, h2, mean_offspring_x
def run_evolution_full(sigma_v, n_pop, n_gen, beta, sigma_e, seed=42,
mode='gauss', width=0.10):
rng = random.Random(seed)
genes = [TARGET + rng.gauss(0, 0.1) for _ in range(n_pop)]
Ss, h2s, means_x = [], [], []
for gen in range(n_gen):
genes, S, h2, mean_x = run_generation_record(
genes, sigma_v, sigma_e, beta, rng, mode=mode, width=width)
Ss.append(S)
h2s.append(h2)
means_x.append(mean_x)
return Ss, h2s, means_x
def window_ratio(Ss, h2s, means_x, w_start, w_len, beta, target):
seg_S = Ss[w_start:w_start + w_len]
seg_h2 = h2s[w_start:w_start + w_len]
seg_mx = means_x[w_start:w_start + w_len]
S_mean = float(np.mean(seg_S))
h2_mean = float(np.mean(seg_h2))
mx_mean = float(np.mean(seg_mx))
delta = mx_mean - target
delta_theory = beta * h2_mean * S_mean / (1 - beta)
if abs(delta_theory) < 1e-12:
return float('nan'), S_mean, h2_mean, delta, delta_theory
return delta / delta_theory, S_mean, h2_mean, delta, delta_theory
def check_monotone_to_one(values, tol=0.02):
diffs = [values[i+1] - values[i] for i in range(len(values) - 1)]
n_toward = sum(1 for d in diffs if d < 0)
last = values[-1]
if n_toward == len(diffs) and abs(last - 1.0) < tol:
return "单调向1收敛"
if n_toward >= len(diffs) - 1 and abs(last - 1.0) < tol:
return "近单调向1收敛"
return "非单调"
def check_stable_offset(values, tol=0.01):
mean_v = float(np.mean(values))
spread = max(values) - min(values)
if spread < tol and abs(mean_v - 1.0) > 0.02:
return "稳定偏离1 (offset={:.4f})".format(mean_v - 1.0)
return "非稳定偏离"
def check_random_walk(values, tol=0.02):
diffs = [values[i+1] - values[i] for i in range(len(values) - 1)]
signs = [1 if d > 0 else -1 for d in diffs]
sign_changes = sum(1 for i in range(len(signs) - 1) if signs[i] != signs[i+1])
spread = max(values) - min(values)
if sign_changes >= len(diffs) // 2 and spread > tol:
return "无趋势随机游走 (spread={:.4f})".format(spread)
return "非随机游走"
def main():
bar("天赐范式第183天:窗口后移三方判决测试")
print(" PID: {}".format(PID))
print()
sub("预登记】三个假说对窗口后移的预测")
print(" 假说A 慢暂态 : 比值随窗口起点单调向1收敛")
print(" 假说B 系统偏差(Jensen): 稳定偏离1,不随窗口动")
print(" 假说C 纯漂变 : 单seed值附近随机游走,无趋势")
print()
print(" 测试参数:")
print(" sigma_v in {0.40, 0.80, 1.50}")
print(" seeds = [42, 0, 1, 2, 3, 4] (6个)")
print(" 窗口起点 = [100, 200, 300, 500]")
print(" 窗长 = 400")
print(" 总代数 = {}".format(N_TOTAL_GEN))
print(" beta={}, sigma_e={}, N_pop={}, select_frac={}".format(
BETA, SIGMA_E, N_POP, SELECT_FRAC))
print()
print(" 理论疑问(用户提出):")
print(" beta=0.3时均值位移时间常数≈1/(1-beta)≈1.4代")
print(" 方差时间常数≈1/(1-beta^2)≈1.1代")
print(" warmup=100是约70个时间常数,暂态理论上早死透")
print(" 伙伴观察到的'单调向1收敛'可能是噪声呈现的假趋势")
print()
sub("步骤1】逐seed逐窗口比值表")
print(" 每个seed跑一次{}代,在不同窗口起点切片取均值算比值".format(N_TOTAL_GEN))
print()
all_results = {}
for sigma_v in TEST_SIGMAS:
print(" --- sigma_v = {:.2f} ---".format(sigma_v))
print(" | seed | w=100 | w=200 | w=300 | w=500 | 趋势检查 |")
print(" |------|---------|---------|---------|---------|----------|")
seed_ratios = []
for seed in TEST_SEEDS:
Ss, h2s, means_x = run_evolution_full(
sigma_v, N_POP, N_TOTAL_GEN, BETA, SIGMA_E, seed=seed)
ratios = []
for w_start in WINDOW_STARTS:
r, _, _, _, _ = window_ratio(
Ss, h2s, means_x, w_start, WINDOW_LEN, BETA, TARGET)
ratios.append(r)
seed_ratios.append(ratios)
trend = check_monotone_to_one(ratios)
print(" | {:>4d} | {:7.4f} | {:7.4f} | {:7.4f} | {:7.4f} | {} |".format(
seed, ratios[0], ratios[1], ratios[2], ratios[3], trend))
print()
all_results[sigma_v] = seed_ratios
sub("步骤2】跨seed汇总------每个sigma_v各窗口起点的mean+-std")
print(" (跨6个seed的统计;这是判决的核心表)")
print()
print(" | sigma_v | w=100 mean+-std | w=200 mean+-std | w=300 mean+-std | w=500 mean+-std |")
print(" |---------|----------------------|----------------------|----------------------|----------------------|")
summary = {}
for sigma_v in TEST_SIGMAS:
seed_ratios = all_results[sigma_v]
cols = []
for j in range(len(WINDOW_STARTS)):
col_vals = [seed_ratios[i][j] for i in range(len(seed_ratios))]
cols.append(col_vals)
parts = []
for col_vals in cols:
m = float(np.mean(col_vals))
s = float(np.std(col_vals))
parts.append((m, s))
summary[sigma_v] = parts
print(" | {:.2f} | {:7.4f} +- {:7.4f} | {:7.4f} +- {:7.4f} | {:7.4f} +- {:7.4f} | {:7.4f} +- {:7.4f} |".format(
sigma_v,
parts[0][0], parts[0][1],
parts[1][0], parts[1][1],
parts[2][0], parts[2][1],
parts[3][0], parts[3][1]))
print()
sub("步骤3】判决辅助------三个假说逐一检验")
print(" 对每个sigma_v,看跨seed均值的窗口序列 [w100, w200, w300, w500]")
print()
for sigma_v in TEST_SIGMAS:
parts = summary[sigma_v]
means_seq = [p[0] for p in parts]
print(" sigma_v = {:.2f}:".format(sigma_v))
print(" 跨seed均值序列: [{:.4f}, {:.4f}, {:.4f}, {:.4f}]".format(
means_seq[0], means_seq[1], means_seq[2], means_seq[3]))
print(" 距1.0的偏差 : [{:+.4f}, {:+.4f}, {:+.4f}, {:+.4f}]".format(
means_seq[0]-1, means_seq[1]-1, means_seq[2]-1, means_seq[3]-1))
mono = check_monotone_to_one(means_seq)
stable = check_stable_offset(means_seq)
rw = check_random_walk(means_seq)
print(" 假说A 慢暂态 : {}".format(mono))
print(" 假说B 系统偏差 : {}".format(stable))
print(" 假说C 纯漂变 : {}".format(rw))
spread = max(means_seq) - min(means_seq)
print(" 窗口间spread : {:.4f}".format(spread))
last_dev = abs(means_seq[-1] - 1.0)
first_dev = abs(means_seq[0] - 1.0)
print(" |偏差|从{:.4f}(w100)到{:.4f}(w500)".format(first_dev, last_dev))
if last_dev < first_dev and mono.startswith("单调"):
print(" -> 偏差随窗口后移减小且单调:支持慢暂态")
elif spread < 0.005 and abs(float(np.mean(means_seq)) - 1.0) > 0.02:
print(" -> 窗口间几乎不动且偏离1:支持系统偏差")
else:
print(" -> 需人工判断(看趋势+spread+偏差方向)")
print()
sub("步骤4】单seed轨迹细看------seed=42(原偏差就是这颗出的)")
print(" 看seed=42在每个sigma_v下的逐窗口比值,判断是趋势还是噪声")
print()
print(" | sigma_v | w=100 | w=200 | w=300 | w=500 | 单调? |")
print(" |---------|---------|---------|---------|---------|-------|")
for sigma_v in TEST_SIGMAS:
seed_idx = TEST_SEEDS.index(42)
ratios = all_results[sigma_v][seed_idx]
mono = check_monotone_to_one(ratios)
print(" | {:.2f} | {:7.4f} | {:7.4f} | {:7.4f} | {:7.4f} | {} |".format(
sigma_v, ratios[0], ratios[1], ratios[2], ratios[3], mono))
print()
sub("步骤5】更细窗口切片------每100代一个比值(seed=42)")
print(" 窗口起点从100到500每50代步进,看曲线形状")
print()
fine_starts = list(range(100, 501, 50))
for sigma_v in TEST_SIGMAS:
print(" --- sigma_v = {:.2f}, seed=42 ---".format(sigma_v))
Ss, h2s, means_x = run_evolution_full(
sigma_v, N_POP, N_TOTAL_GEN, BETA, SIGMA_E, seed=42)
fine_ratios = []
for w_start in fine_starts:
r, _, _, _, _ = window_ratio(
Ss, h2s, means_x, w_start, WINDOW_LEN, BETA, TARGET)
fine_ratios.append(r)
print(" | w_start | ratio | dev from 1 |")
print(" |---------|---------|------------|")
for i, w_start in enumerate(fine_starts):
r = fine_ratios[i]
print(" | {:>7d} | {:7.4f} | {:+10.4f} |".format(w_start, r, r - 1.0))
diffs = [fine_ratios[i+1] - fine_ratios[i] for i in range(len(fine_ratios)-1)]
n_down = sum(1 for d in diffs if d < 0)
n_up = sum(1 for d in diffs if d > 0)
print(" 逐50代步进:{}步下降,{}步上升(共{}步)".format(n_down, n_up, len(diffs)))
print()
bar("三方判决结果汇总")
print(" 将上述数据交给用户做最终判决。")
print()
print(" 判决规则(预登记):")
print(" 若跨seed均值随窗口起点单调向1收敛 -> 假说A慢暂态成立")
print(" 若跨seed均值稳定偏离1且窗口间spread<0.005 -> 假说B系统偏差成立")
print(" 若跨seed均值无趋势且窗口间波动大 -> 假说C纯漂变成立")
print()
print(" 连带警告:若慢暂态被证实,主实验warmup=100偏短,")
print(" 所有表格需按新warmup重新生成,183-1正文也需同步。")
print("=" * 78)
if __name__ == "__main__":
main()
