羊车三门问题Python模拟

突然想到这个,然后想模拟做个实验,代码写得多了些不够简洁,多包涵。

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"]=["SimHei"] 
plt.rcParams["axes.unicode_minus"]=False

# 生成随机列表, 1表示选对的跑车, 0表示羊
def create_random_array(doors=3):
    array = np.zeros(doors)
    random_index = np.random.randint(0, len(array))
    array[random_index] = 1

    return array

# 从随机列表中选择一个随机的数, choice表示随机选的值是多少例如0或1, random_chice_index表示选的是第几个
def choice(random_array):
    random_choice_index = np.random.randint(0, len(random_array))
    choice = random_array[random_choice_index]

    return choice, random_choice_index

# 从原先随机产生的列表中排除两个值, 由于主持人不能排除跑车, 还有原先嘉宾选的门, 因此要先获取能排除哪些
def excluded(choice_index, random_array):
    # 做一次遍历用于装填能排除哪些, 条件是不能是原先的选择和得是山羊,所以索引不能等于choice_index,也不能是1
    # can_excluded装填的是索引
    can_excluded = []
    for i in range(len(random_array)):
        if (i != choice_index) and (random_array[i] != 1):
            can_excluded.append(i)

    # 如果情况是嘉宾选择了的是山羊, 那么意味着主持人只有一个选项能用来给他排除, 就直接返回去除后的列表和去除项的索引
    if len(can_excluded) == 1:
        excluded_array = np.delete(random_array, can_excluded)
        return excluded_array, can_excluded
    
    # 如果能排除的选项有多个, 那么会随机从能排除的选项中抽取一个用于排除, 注意这时候排除的索引是excluded
    else:
        excluded_index = np.random.randint(0, len(can_excluded))
        excluded = can_excluded[excluded_index]
        excluded_array = np.delete(random_array, excluded)
        return excluded_array, excluded
    
# 用于模拟测试, epoch是轮数, change_select表示是否要跟换
def test(epoch=10000, change_select=False, doors=3):
    choice_list = []
    for _ in range(epoch):
        random_array = create_random_array(doors)
        choice_value, choice_index = choice(random_array)
        excluded_array, excluded_index = excluded(choice_index, random_array)

        # 如果要更换, 就相当于不要原先的choice_index, 也不可能选被主持人排除的excluded_index,所以选剩下的随机来一个
        if change_select:
            mask = np.ones(len(random_array), dtype=bool)
            mask[excluded_index] = False
            mask[choice_index] = False

            choice_list.append(np.random.choice(random_array[mask]))
        
        # 如果不更换, 就拿原先的值
        else:
            choice_list.append(choice_value)

    return choice_list

# 用于计算多轮选择下选对的次数和占比
def calculate_accuracy(choice_list):
    total_count = len(choice_list)  # 列表中总数的个数
    ones_count = choice_list.count(1)  # 列表中值为1的数值的个数
    accuracy = ones_count / total_count  # 值为1的数值占总数的比例

    return accuracy, ones_count

def plotbar(x_labels, values, colors):
    x = np.arange(len(x_labels))

    fig, ax = plt.subplots()
    rects = ax.bar(x, values, color=colors)

    ax.set_xticks(x)
    ax.set_xticklabels(x_labels)
    ax.set_title("选中次数")

    plt.show()

experiment = test(change_select=True)
control = test(change_select=False)
experiment_acc_1, experiment_count_1 = calculate_accuracy(experiment)
control_acc_1, control_count_1 = calculate_accuracy(control)

print('实验组:', experiment_acc_1, '%')
print('对照组:', control_acc_1, '%')

labels = ['对照组', '实验组']
values = [experiment_count_1, control_count_1]

colors = ['orange', 'c']
plotbar(labels, values, colors)

 

 实验组: 0.6611 %
 对照组: 0.341 %
experiment = test(change_select=True, doors=4)
control = test(change_select=False, doors=4)
experiment_acc, experiment_count = calculate_accuracy(experiment)
control_acc, control_count = calculate_accuracy(control)

print('实验组:', experiment_acc, '%')
print('对照组:', control_acc, '%')

labels = ['对照组', '实验组']
values = [experiment_count, control_count]

colors = ['orange', 'c']
plotbar(labels, values, colors)
实验组: 0.3826 %
对照组: 0.2525 %
experiment_acc_l, experiment_count_l = [], []
control_acc_l, control_count_l = [], []
for doors in range(3,10):
    experiment = test(change_select=True, doors=doors)
    control = test(change_select=False, doors=doors)
    experiment_acc, experiment_count = calculate_accuracy(experiment)
    control_acc, control_count = calculate_accuracy(control)
    
    experiment_acc_l.append(experiment_acc)
    experiment_count_l.append(experiment_count)
    control_acc_l.append(control_acc)
    control_count_l.append(control_count)

fig, ax = plt.subplots()

ax.plot(range(3, 10), experiment_acc_l, 'b-', label='实验组')
ax.set_ylabel('准确率')
ax.set_title('不同门数下两组对照')

ax.plot(range(3, 10), control_acc_l, 'r-', label='对照组')
ax.set_xlabel('门数')
plt.legend()
plt.show()

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值