吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2041|回复: 41
收起左侧

[Python 转载] [Py]人类两性博弈模拟

[复制链接]
LuLuWuWei1120 发表于 2026-8-15 12:13
本帖最后由 LuLuWuWei1120 于 2026-8-19 11:27 编辑

---

📝 说明

本模型的理论基础来源附件中文章《人类两性博弈》,由《自私的基因》中内容进一步建模,目的为:使研究对象由普遍两性生物博弈转向人类博弈。

《人类两性博弈》文章为本人与ai探讨后ai的总结化表述,我希望任何人都可以阅读一下其中的无建模部分(即非对男女各种策略推导的部分),有利于理解男女双方观念及根源,并且在恋爱关系中减少自身损失。另外,本人非专业人士,无相关经验,无法给出关于男女双方的的任何建设性结论。有错误或不准确的之处是可能的,请理性思考,明辨是非,批判吸收。

模拟内容并不考虑任何情感因素,请勿盲目代入现实,将本文作为纯粹的智慧生物利益博弈即可(情感因素难以抽象化,人各有情)。

模拟程序为ai独立实现(本人目前并无时间写代码)。

亲密关系策略演化博弈模型

一个基于个体演化博弈论的计算机模拟框架,用于研究亲密关系中忠诚、薄情、变化型、欺骗型策略在群体中的动态演化。本项目完全复现了《人类两性博弈》中描述的概念,并可用于探索不同初始条件、收益参数下的社会演化路径。


📖 项目简介

本模拟程序构建了一个离散世代、随机配对、适应度驱动的演化环境。每个个体携带以下属性:

· 性别(男/女)
· 策略(Lc, Lk, U, V, D)
· 生育期望(S 或 N)

个体在每一代中随机配对,依据双方策略和期望发生资源转移、生育、检查与欺骗识别,累积适应度。随后按适应度比例选择父母,产生下一代,并允许突变。

该模型旨在从生物投资不对称和进化恐惧出发,分析信任、欺骗、忠诚、躺平等社会现象背后的博弈论根源。


🧠 理论背景

模型基于以下核心理论假设(详见理论文档):

· 亲代投资不对称:女性是高投入锁定者(卵子稀缺、妊娠、哺乳),男性是低投入即走者。
· 女性进化恐惧(被弃恐惧):女性担心生育后失去男性支持,故倾向于筛选长期投资承诺。
· 男性进化恐惧(被欺恐惧):男性担心抚养非亲生后代,故倾向于筛选亲子确定性。
· 人类演化两大突变:隐蔽排卵 + 隐性发情,迫使人类走向配对绑定,使忠贞成为交易筹码。
· 现代环境颠覆:女性经济独立和避孕技术使“资源换忠贞”协议失效,催生多元化策略。


🎯 策略集合

策略代号 名称 说明
Lc 随意型忠诚 默认信任,零验证成本,适合高信任环境
Lk 检查型忠诚 忠诚但附加验证程序(体检、孕检、财务透明),防御欺骗
U 薄情 低投入、短期存在,拒绝长期绑定
V 变化型 根据对方展示策略动态切换(遇L则L,遇U则U)
D 欺骗型 伪装为L以骗取对方核心投资,事后撤离

生育期望:

· S(期望有子):以基因传递为终极目标,愿接受验证。
· N(期望无子):以生存舒适度为终极目标,排斥长期绑定与生育成本。


⚙️ 核心参数

运行时可自定义的参数包括:

参数 含义 默认值
POP_SIZE 种群总大小(男女各半) 2000
NUM_GENERATIONS 演化代数 200
MUTATION_RATE 策略/期望突变概率 0.01
V_GENE 每个后代的基因收益 10.0
C_FEMALE_BIRTH 女性生育成本 5.0
I_M_L 男性忠诚投入(资源转移) 3.0
I_M_D 男性欺骗伪装成本 1.0
S_M 忠诚男性的额外抚养支持 2.0
C_K 检查型忠诚的验证成本 2.0
初始策略分布 五类策略在男/女中的初始概率 均匀(各20%)
S/N 初始比例 男/女期望生育的比例 各50%


🚀 运行方式

环境要求

· Python
· 无需额外第三方库(仅使用标准库 random, csv, math, sys, collections)

快速启动

python simulation.py

程序启动后,您将看到交互式菜单:

========== 亲密关系策略演化模型(高性能版) ==========
请选择运行模式:
1. 自定义配置
2. 默认配置(200代,均匀初始)
3. 完全随机(500~2000代,所有参数随机)

· 选项1:逐步输入种群大小、代数、突变率、收益参数、初始策略概率、S/N比例。
· 选项2:使用预设默认值快速运行。
· 选项3:一键运行,所有参数(包括收益参数)均在合理范围内随机生成,代数范围500~2000,适合探索性实验。

输出

模拟结束后,当前目录下会生成 simulation_results.csv,包含每代的统计信息:

· generation:代数
· avg_fitness:种群平均适应度
· S_ratio:总体S期望比例
· male_ratio, female_ratio:实际性别比例(自然演化)
· M_LC, M_LK, M_U, M_V, M_D:男性各策略频率
· F_LC, F_LK, F_U, F_V, F_D:女性各策略频率


📊 结果解读与理论验证

典型演化模式(示例)

模式一:完整循环(“完美循环”)
当初始条件中欺骗型(D)形成有效集群时,系统会依次经历:

  1. D扩张 → 2. Lk防御崛起 → 3. U“躺平”替代 → 4. Lc回归重建信任。
    此模式完整复现了理论中的四大循环。

模式二:U主导稳态(“低信任均衡”)
若初始D比例不足或Lc较早被U替代,系统可能锁定在U占主导的状态,Lc和Lk均无法大规模复兴,D也因失去寄生宿主而长期低迷。这是路径依赖的典型案例。

模式三:其他路径
因随机种子、初始参数不同,还可能观察到双欺骗共振、S/N潮汐、长周期振荡等。

所有结果均由群体选择压力自然涌现,无任何预设脚本干预。


🔬 模型逻辑要点

· 收益计算:完全依据理论设定,包括资源转移、生育成本、检查成本、基因收益等。
· 欺骗与检查:Lk能识破D(无论性别),一旦识破则无生育,双方承担各自成本。
· V策略响应:V根据对方展示的策略切换行为(遇L则L,遇U则U),但自身期望不影响行为。
· 性别比例演化:下一代性别随机决定,不强制男女等量,允许性别比例受选择压力漂移。
· 适应度选择:采用指数权重轮盘赌,避免负适应度问题。



纯代码部分:
[Python] 纯文本查看 复制代码
#!/usr/bin/env python3
"""
亲密关系策略演化博弈模型(高性能版)
策略编码:0=Lc, 1=Lk, 2=U, 3=V, 4=D
期望编码:0=S, 1=N
随机模式:种群500~4000,代数500~2000,其他参数在合理区间随机
"""

import random
import csv
import math
import sys
from collections import defaultdict

# ==================== 常量编码 ====================
LC, LK, U, V, D = 0, 1, 2, 3, 4
S_EXP, N_EXP = 0, 1

# ==================== 默认参数 ====================
DEFAULT_POP_SIZE = 2000
DEFAULT_NUM_GENERATIONS = 200
DEFAULT_MUTATION_RATE = 0.01
DEFAULT_V_GENE = 10.0
DEFAULT_C_FEMALE_BIRTH = 5.0
DEFAULT_I_M_L = 3.0
DEFAULT_I_M_D = 1.0
DEFAULT_S_M = 2.0
DEFAULT_C_K = 2.0

DEFAULT_MALE_STRAT_PROBS = [0.2, 0.2, 0.2, 0.2, 0.2]
DEFAULT_FEMALE_STRAT_PROBS = [0.2, 0.2, 0.2, 0.2, 0.2]
DEFAULT_MALE_S_PROB = 0.5
DEFAULT_FEMALE_S_PROB = 0.5

# ==================== 个体类 ====================
class Individual:
    __slots__ = ('gender', 'strategy', 'expect', 'fitness')
    def __init__(self, gender, strategy, expect):
        self.gender = gender      # 0=男性, 1=女性
        self.strategy = strategy  # 0~4
        self.expect = expect      # 0=S, 1=N
        self.fitness = 0.0

# ==================== 核心演化函数 ====================
def evolve_generation(pop, gen, params):
    v_gene = params['V_gene']
    c_female = params['C_female_birth']
    i_m_l = params['I_m_L']
    i_m_d = params['I_m_D']
    s_m = params['S_m']
    c_k = params['C_k']
    mu = params['mutation_rate']
    
    n = len(pop)
    target_size = n
    half = n // 2
    
    shuffled = pop[:]
    random.shuffle(shuffled)
    pairs = [(shuffled[i], shuffled[i+half]) for i in range(half)]
    
    for a, b in pairs:
        if a.gender == 0 and b.gender == 1:
            m, f = a, b
        elif a.gender == 1 and b.gender == 0:
            m, f = b, a
        else:
            continue
        
        f_show = LC if f.strategy == D else f.strategy
        
        if m.strategy == V:
            m_behavior = LC if (f_show == LC or f_show == LK) else U
        elif m.strategy == LC or m.strategy == LK:
            m_behavior = LC
        elif m.strategy == D:
            m_behavior = D
        else:
            m_behavior = U
        
        if m_behavior == LC:
            I_m = i_m_l
        elif m_behavior == D:
            I_m = i_m_d
        else:
            I_m = 0.0
        
        S_m_actual = s_m if (m_behavior == LC and m.expect == S_EXP and f.expect == S_EXP) else 0.0
        
        if (m.strategy == LK and f.strategy == D) or (f.strategy == LK and m.strategy == D):
            m_fit = -I_m - (c_k if m.strategy == LK else 0.0)
            f_fit = I_m - (c_k if f.strategy == LK else 0.0)
            m.fitness += m_fit
            f.fitness += f_fit
            continue
        
        offspring = (m.expect == S_EXP and f.expect == S_EXP)
        m_gene = v_gene if offspring and not (f.strategy == D and f.expect == S_EXP) else 0.0
        f_gene = v_gene if offspring else 0.0
        
        m_fit = m_gene - I_m - S_m_actual - (c_k if m.strategy == LK else 0.0)
        f_fit = f_gene + I_m + S_m_actual - (c_female if offspring else 0.0) - (c_k if f.strategy == LK else 0.0)
        
        m.fitness += m_fit
        f.fitness += f_fit
    
    # ---- 统计 ----
    stats = {
        'generation': gen,
        'avg_fitness': 0.0,
        'S_ratio': 0.0,
        'male_ratio': 0.0,
        'female_ratio': 0.0,
        'M_LC': 0.0, 'M_LK': 0.0, 'M_U': 0.0, 'M_V': 0.0, 'M_D': 0.0,
        'F_LC': 0.0, 'F_LK': 0.0, 'F_U': 0.0, 'F_V': 0.0, 'F_D': 0.0,
    }
    count = {'M': [0]*5, 'F': [0]*5}
    s_count = 0
    fit_sum = 0.0
    male_count = 0
    for ind in pop:
        if ind.gender == 0:
            male_count += 1
            count['M'][ind.strategy] += 1
        else:
            count['F'][ind.strategy] += 1
        if ind.expect == S_EXP:
            s_count += 1
        fit_sum += ind.fitness
    
    stats['avg_fitness'] = fit_sum / n
    stats['S_ratio'] = s_count / n
    stats['male_ratio'] = male_count / n
    stats['female_ratio'] = 1 - stats['male_ratio']
    for g in ['M', 'F']:
        for i, s_name in enumerate(['LC', 'LK', 'U', 'V', 'D']):
            stats[f'{g}_{s_name}'] = count[g][i] / n
    
    # ---- 选择繁殖 ----
    weights = [math.exp(max(-10, min(10, ind.fitness))) for ind in pop]
    total_w = sum(weights)
    if total_w == 0:
        probs = [1.0 / n] * n
    else:
        probs = [w / total_w for w in weights]
    
    parent_indices = random.choices(range(n), weights=probs, k=2 * target_size)
    new_pop = []
    strat_pool = [LC, LK, U, V, D]
    
    for i in range(0, 2 * target_size, 2):
        idx1 = parent_indices[i]
        idx2 = parent_indices[i+1]
        if idx1 == idx2:
            idx2 = random.randrange(n)
        
        p1 = pop[idx1]
        p2 = pop[idx2]
        
        if random.random() < 0.5:
            strat = p1.strategy
        else:
            strat = p2.strategy
        if random.random() < 0.5:
            expect = p1.expect
        else:
            expect = p2.expect
        
        gender = 0 if random.random() < 0.5 else 1
        
        if gender == 0 and strat == D:
            expect = S_EXP
        
        if random.random() < mu:
            strat = random.choice(strat_pool)
            if gender == 0 and strat == D:
                expect = S_EXP
        if random.random() < mu:
            expect = N_EXP if expect == S_EXP else S_EXP
            if gender == 0 and strat == D:
                expect = S_EXP
        
        child = Individual(gender, strat, expect)
        child.fitness = 0.0
        new_pop.append(child)
    
    return new_pop, stats

# ==================== 种群生成 ====================
def generate_population(size, male_strat_probs, female_strat_probs, male_s_prob, female_s_prob):
    pop = []
    num_males = size // 2
    num_females = size - num_males
    for _ in range(num_males):
        strat = random.choices([LC, LK, U, V, D], weights=male_strat_probs, k=1)[0]
        expect = S_EXP if random.random() < male_s_prob else N_EXP
        if strat == D:
            expect = S_EXP
        pop.append(Individual(0, strat, expect))
    for _ in range(num_females):
        strat = random.choices([LC, LK, U, V, D], weights=female_strat_probs, k=1)[0]
        expect = S_EXP if random.random() < female_s_prob else N_EXP
        pop.append(Individual(1, strat, expect))
    random.shuffle(pop)
    return pop

def generate_random_population(size):
    pop = []
    num_males = size // 2
    num_females = size - num_males
    for _ in range(num_males):
        strat = random.choice([LC, LK, U, V, D])
        expect = S_EXP if random.random() < 0.5 else N_EXP
        if strat == D:
            expect = S_EXP
        pop.append(Individual(0, strat, expect))
    for _ in range(num_females):
        strat = random.choice([LC, LK, U, V, D])
        expect = S_EXP if random.random() < 0.5 else N_EXP
        pop.append(Individual(1, strat, expect))
    random.shuffle(pop)
    return pop

# ==================== 模拟主循环 ====================
def run_simulation(params):
    pop_size = params['pop_size']
    num_gens = params['num_generations']
    random_init = params.get('random_init', False)
    
    if random_init:
        pop = generate_random_population(pop_size)
        print("使用完全随机初始种群")
    else:
        pop = generate_population(
            pop_size,
            params['male_strat_probs'],
            params['female_strat_probs'],
            params['male_s_prob'],
            params['female_s_prob']
        )
    
    records = []
    print("进度:", end='', flush=True)
    for gen in range(num_gens):
        pop, stats = evolve_generation(pop, gen, params)
        records.append(stats)
        if gen % 20 == 0:
            print(f"\nGen {gen}: avg_f={stats['avg_fitness']:.3f}, S={stats['S_ratio']:.3f}, M_ratio={stats['male_ratio']:.3f}")
        else:
            print('.', end='', flush=True)
    print("\n模拟完成。")
    return records

def save_records(records, filename="simulation_results.csv"):
    if not records:
        return
    fieldnames = list(records[0].keys())
    with open(filename, 'w', newline='', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        for rec in records:
            writer.writerow(rec)
    print(f"Results saved to {filename}")

# ==================== 交互配置 ====================
def get_float(prompt, default):
    while True:
        try:
            val = input(f"{prompt} (default {default}): ")
            if val.strip() == '':
                return default
            return float(val)
        except ValueError:
            print("请输入数字")

def get_int(prompt, default):
    while True:
        try:
            val = input(f"{prompt} (default {default}): ")
            if val.strip() == '':
                return default
            return int(val)
        except ValueError:
            print("请输入整数")

def get_prob_list(prompt, default, length=5):
    print(f"{prompt} (输入5个空格分隔的概率,总和为1,默认: {' '.join(map(str, default))})")
    while True:
        line = input().strip()
        if line == '':
            return default[:]
        parts = line.split()
        if len(parts) != length:
            print(f"需要输入{length}个数字")
            continue
        try:
            probs = [float(p) for p in parts]
            if abs(sum(probs) - 1.0) > 0.001:
                print("概率之和不等于1,请重新输入")
                continue
            return probs
        except ValueError:
            print("请输入有效数字")

def random_param(min_val, max_val, is_int=False):
    if is_int:
        return random.randint(int(min_val), int(max_val))
    else:
        return random.uniform(min_val, max_val)

def generate_random_params():
    pop_size = random_param(500, 4000, True)
    if pop_size % 2 != 0:
        pop_size += 1
    return {
        'pop_size': pop_size,
        'num_generations': random_param(500, 2000, True),   # 改为500~2000代
        'mutation_rate': random_param(0.003, 0.03),
        'V_gene': random_param(5, 15),
        'C_female_birth': random_param(2, 8),
        'I_m_L': random_param(1, 5),
        'I_m_D': random_param(0.3, 2),
        'S_m': random_param(0.5, 4),
        'C_k': random_param(0.5, 3),
        'random_init': True,
    }

def interactive_config():
    print("========== 亲密关系策略演化模型(高性能版) ==========")
    print("请选择运行模式:")
    print("1. 自定义配置")
    print("2. 默认配置(200代)")
    print("3. 完全随机(500~2000代)")
    choice = input("输入 1, 2 或 3: ").strip()
    
    if choice == '3':
        params = generate_random_params()
        print("\n随机生成的参数:")
        for k, v in params.items():
            if k != 'random_init':
                print(f"  {k}: {v:.3f}" if isinstance(v, float) else f"  {k}: {v}")
        return params
    
    elif choice == '2':
        return {
            'pop_size': DEFAULT_POP_SIZE,
            'num_generations': DEFAULT_NUM_GENERATIONS,
            'mutation_rate': DEFAULT_MUTATION_RATE,
            'V_gene': DEFAULT_V_GENE,
            'C_female_birth': DEFAULT_C_FEMALE_BIRTH,
            'I_m_L': DEFAULT_I_M_L,
            'I_m_D': DEFAULT_I_M_D,
            'S_m': DEFAULT_S_M,
            'C_k': DEFAULT_C_K,
            'male_strat_probs': DEFAULT_MALE_STRAT_PROBS[:],
            'female_strat_probs': DEFAULT_FEMALE_STRAT_PROBS[:],
            'male_s_prob': DEFAULT_MALE_S_PROB,
            'female_s_prob': DEFAULT_FEMALE_S_PROB,
            'random_init': False,
        }
    
    else:
        print("\n--- 基本参数 ---")
        pop_size = get_int("种群总大小", DEFAULT_POP_SIZE)
        if pop_size % 2 != 0:
            pop_size += 1
            print(f"调整为偶数: {pop_size}")
        num_gens = get_int("演化代数", DEFAULT_NUM_GENERATIONS)
        mu = get_float("突变率", DEFAULT_MUTATION_RATE)
        
        print("\n--- 收益参数 ---")
        V = get_float("后代基因价值 V", DEFAULT_V_GENE)
        Cfb = get_float("女性生育成本 C_f", DEFAULT_C_FEMALE_BIRTH)
        I_L = get_float("男性忠诚投入 I_m_L", DEFAULT_I_M_L)
        I_D = get_float("男性欺骗伪装成本 I_m_D", DEFAULT_I_M_D)
        S = get_float("男性忠诚抚养支持 S_m", DEFAULT_S_M)
        Ck = get_float("检查成本 C_k", DEFAULT_C_K)
        
        print("\n--- 初始策略分布 ---")
        print("男性策略概率 [Lc, Lk, U, V, D]:")
        male_probs = get_prob_list("", DEFAULT_MALE_STRAT_PROBS)
        print("女性策略概率 [Lc, Lk, U, V, D]:")
        female_probs = get_prob_list("", DEFAULT_FEMALE_STRAT_PROBS)
        
        male_s = get_float("男性中 S 期望比例", DEFAULT_MALE_S_PROB)
        female_s = get_float("女性中 S 期望比例", DEFAULT_FEMALE_S_PROB)
        
        return {
            'pop_size': pop_size,
            'num_generations': num_gens,
            'mutation_rate': mu,
            'V_gene': V,
            'C_female_birth': Cfb,
            'I_m_L': I_L,
            'I_m_D': I_D,
            'S_m': S,
            'C_k': Ck,
            'male_strat_probs': male_probs,
            'female_strat_probs': female_probs,
            'male_s_prob': male_s,
            'female_s_prob': female_s,
            'random_init': False,
        }

def main():
    params = interactive_config()
    print("\n开始模拟...")
    records = run_simulation(params)
    save_records(records, "simulation_results.csv")
    print("模拟完成。结果已保存至 simulation_results.csv")

if __name__ == "__main__":
    main()


此模拟对初始条件较为敏感,几次模拟的结果可能完全不同,但往往也符合理论推理。有兴趣的话,可自行写脚本,进行上百次千代级的模拟,将理论文件和日志csv文件丢给ai,可能可以从从统计学意义上得到社会两性问题上,总体的趋势吧。

附件:
https://wwbdi.lanzouu.com/irCIf42hnypg

免费评分

参与人数 7吾爱币 +7 热心值 +5 收起 理由
flchen + 1 热心回复!
染色体 + 1 + 1 热心回复!
cqding + 1 + 1 我很赞同!
oldbabyjsx + 1 谢谢@Thanks!
freckle + 1 + 1 谢谢@Thanks!
lspghs9.10plus + 1 + 1 我很赞同!
lsb2pojie + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| LuLuWuWei1120 发表于 2026-8-16 09:07
budongdashi 发表于 2026-8-15 19:05
哈哈 最终结果是什么 比如博弈下来男的优势 应该怎么样

仅仅考虑这个过程的前提下,没有性别可以占据优势,他们只是选择策略Lc(随意忠诚型),Lk(严查忠诚型),U(薄情),D(欺诈型),V(变化型)中的一种,然后进行博弈,双方的优劣在总体平均看应该是等同的。从生物学角度,由于生育需要男女共同配合,如果某个性别在此过程占据优势,可能另一个性别的基因受自然选择进化尝试补平差距(即相互开展进化的竞赛),可能生育者倾向于生这种优势性别(最极端的情况下,只有这一种优势性别,然后全部灭亡)
fh20 发表于 2026-8-15 12:23
syelbslsy 发表于 2026-8-15 14:22
777444 发表于 2026-8-15 14:57
能不能 换成研究经济
xbd26248 发表于 2026-8-15 15:05
好评,相亲的可以先模拟一下,再决定要不要继续
shifan2003 发表于 2026-8-15 16:03
可以拿去测试下女朋友
 楼主| LuLuWuWei1120 发表于 2026-8-15 16:05
777444 发表于 2026-8-15 14:57
能不能 换成研究经济

研究经济应该有很多方向吧,而且我目前对经济的研究比较少,自认为没有足够的能力将经济抽象化建模。
changheyunian 发表于 2026-8-15 18:41
这是文本软件模拟器,还是游戏软件模拟器
budongdashi 发表于 2026-8-15 19:05
哈哈 最终结果是什么 比如博弈下来男的优势 应该怎么样
wqs0601 发表于 2026-8-15 19:27
啊?明明都是字,为什么我就看不懂了呢?博弈论是这么用的吗?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-6 17:43

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表