"""【未验证 · GPT 级档】S + F + 低秩 组合预演(纯理论,不验证)。

一句话结论:
    GPT 级大模型的函数化路线 = 结构边界(S,按头/层切)+ 功能聚类(F,按激活
    响应聚)+ FFN 低秩(1 阶区域函数)。本例用「玩具尺寸」跑通组合接口、再用
    「GPT 尺寸」做理论体积估算;**不加载、不训练真实 GPT 权重**——本机 12G
    显存装不下,谁有条件谁验证。

对应分型表第四行:GPT 级 = S + F + 低秩(仅预演,不验证)。
"""

import _common  # noqa: F401  # 先导入:完成 src 路径引导(让 import nrfunc 可用)

import numpy as np

import nrfunc


def size_mb(shape):
    return int(np.prod(shape)) * 4 / (1024 * 1024)


def preview_toy_block():
    """玩具尺寸:跑通「S 边界内 F 聚 + 低秩」组合接口,证明可执行。

    构造一个有明显簇结构的玩具 FFN:S 结构边界先把整层划成一块(一层),
    块内再按激活响应 F 聚成 K 区 + 每区 1 阶低秩。
    """
    d_model, ffn, K = 64, 256, 8
    rng = np.random.default_rng(0)
    # 造 K 个簇中心,每个单元归入一个簇(带噪声)——让 F 聚类有意义
    centers = rng.standard_normal((K, d_model))
    assign_true = rng.integers(0, K, size=ffn)
    W_ffn = (centers[assign_true] + 0.1 * rng.standard_normal((ffn, d_model))).astype(np.float64)

    # 激活响应也带同样的簇结构(F 信号依据)
    T = 32
    act_centers = rng.standard_normal((K, T))
    activations = (act_centers[assign_true] + 0.1 * rng.standard_normal((ffn, T))).astype(np.float64)

    res = nrfunc.regionify(W_ffn, signal='F', K=K, order=1, r=8, seed=0,
                           activations=activations)
    print(f'玩具 FFN({ffn}×{d_model})S 边界内 F 聚 {res["K"]} 区 + 低秩:'
          f'解释方差 = {res["explained"]:.4f}')

    # 生成物可还原,重建误差应很小(簇结构明显)
    recon = nrfunc.reconstruct(res)
    err = float(np.linalg.norm(W_ffn - recon) / np.linalg.norm(W_ffn))
    print(f'重建相对误差 = {err:.4f}')


def preview_gpt_scale():
    """GPT 尺寸:只做理论体积估算,不加载权重。"""
    d_model, n_heads, n_layers = 4096, 32, 32
    ffn = 4 * d_model
    print(f'\n[GPT 尺寸理论估算] d_model={d_model}, heads={n_heads}, layers={n_layers}')
    # 单层 FFN 权重(up+down 两块)
    w = d_model * ffn * 2
    print(f'单层 FFN 权重:{w:,} 参 ≈ {w * 4 / (1024 ** 2):.0f} MB(fp32)')
    print(f'全 {n_layers} 层 FFN:{w * n_layers:,} 参 ≈ '
          f'{w * n_layers * 4 / (1024 ** 3):.1f} GB(fp32)')
    # 低秩函数化思路:每层 FFN 按「功能聚类 K 区 + 每区 r 主成分」表达
    #  参数:K×d_model + K×r×d_model + n×r  vs  原 n×d_model(n=ffn)
    # 压缩来自:不再存 n×d_model 独立行,只存 K 个共享函数 + n 个归属索引。
    print('函数化思路:S 按层/头切边界 → F 按激活聚 K 区 → 每区 1 阶低秩(r 主成分)。')
    print('归属索引仅 log2(K) 位/单元;压缩率 = n×D / (K×D + K×r×D + n×r)。')


def main():
    preview_toy_block()

    print('\n[GPT 级入口] regionify_transformer_block()(接口预留):')
    try:
        nrfunc.regionify_transformer_block({})
    except NotImplementedError as e:
        print(f'  触发 NotImplementedError:{e}')

    preview_gpt_scale()

    print('\n[诚实声明] GPT 级为「理论预演、不验证」:本机 RTX 5070 12G 无法加载/'
          '训练 GPT 级权重,责任边界 = 谁有条件谁验证,本库不负责。')


if __name__ == '__main__':
    main()