雪堆博弈实验

雪堆博弈背景

“雪堆”博弈模型又称为“鹰鸽”博弈或者“小鸡”博弈(chicken Game),是一种两人对称博弈模型,描述了两个人相遇时是彼此合作共同受益,还是彼此欺骗来相互报复。雪堆博弈最早来源于这样一个故事:
在一个风雪交加的夜晚,两人相向而来,被一个雪堆所阻,假设铲除这个雪堆使道路通畅需要的代价为c,如果道路通畅则带给每个人的好处量化为b。如果两人一齐动手铲雪,则他们的收益为R=b-c/2;如果只有一人铲雪,虽然两个人都可以回家,但是背叛者逃避了劳动,它的收益为T=b,而合作者的收益为S=b-c;如果两人都选择不合作,两人都被雪堆挡住而无法回家,他们的收益都为P=0。这里假设收益参数满足下面的条件:T>R>S>P。
在这里插入图片描述
雪堆博弈的本质是在初始状态下不断不同的节点通过不断的调整策略从而改变自己的收益,最后直到任意一节点改变策略后他的收益都不会有增加,即达到了一种均衡状态博弈结束,此时更新之后的最终状态中采取合作策略的节点则构成了网络的最小覆盖。具体算法流程图如下所示:
在这里插入图片描述

结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

import random
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd 

class Node():   #定义每一个节点的状态和收益以及总收益
    def __init__(self):
        if (random.random() < 0.5):
            self.state = 'C'  #进行状态的随机初始化
        else:
            self.state = 'D'
        self.value = 0
        self.all_value = 0
        self.neighbour_number = 0
        self.nb = list()

class Net():
    def __init__(self, n):
        self.numbers = n
        self.nodes = list()
        self.edges = list()
        self.reward = 0
        self.initNode()
 
   
    def initNode(self):   #初始化节点
        for _ in range(self.numbers):
            tmp_node = Node()
            self.nodes.append(tmp_node)
    
    def buideNet(self, es):  #构建网络
        for e in es:
            self.edges.append(e)
        self.updateNb()
    def updateNb(self): 
        for a, b in self.edges:
            a.nb.append(self.nodes.index(b))
            b.nb.append(self.nodes.index(a))
        for i in range(self.numbers):
            self.nodes[i].neighbour_number = len(self.nodes[i].nb)
    def calValue(self):   #计算收益值
        for i in range(self.numbers):
            self.nodes[i].all_value = 0    #首先把每个节点的整体收益清零
        for a, b in self.edges:
            a.all_value += rewardMat[a.state][b.state][0]  #计算每个节点的总体收益
            b.all_value += rewardMat[a.state][b.state][1]  
        for i in range(self.numbers):    #计算每个节点的平均代价
            if self.nodes[i].neighbour_number==0:
                self.nodes[i].value=0               
            else:
                self.nodes[i].value = self.nodes[i].all_value / \
                    self.nodes[i].neighbour_number  
    def updateState(self):    #更新矩阵
        self.calValue()
        flag = False
        for i in range(self.numbers):
            if(self.nodes[i].state == 'C'):
                reward1 = self.getReward(i)
                self.nodes[i].state = 'D'
                reward2 = self.getReward(i)
                if(reward2 <= reward1):   #判断是否要调整策略
                    self.nodes[i].state = 'C' 
               # else:
                #    self.nodes[i].state = 'D'

                    continue
                flag = True
                break   #
            elif(self.nodes[i].state == 'D'):
                reward1 = self.getReward(i)
                self.nodes[i].state = 'C'
                reward2 = self.getReward(i)
                if(reward2 <= reward1):
                    self.nodes[i].state = 'D'
                #else:
                #    self.nodes[i].state = 'C'
                    continue
                flag = True
                break   #
        return flag

    def getReward(self, i):  #获得每个节点的收益
        all_value = 0
        for s in self.nodes[i].nb:
            all_value += rewardMat[self.nodes[i].state][self.nodes[s].state][0]
        if self.nodes[i].neighbour_number==0:
            value=0
        else:

            value = all_value / self.nodes[i].neighbour_number  #计算平均收益
        return value

    def getAllReward(self):  #计算总收益
        for a, b in self.edges:
            self.reward += sum(rewardMat[a.state][b.state])
        return self.reward
if __name__ == '__main__':
    r = 0.8
    rewardMat = {'C': {'C': (1, 1), 'D': (1-r, 1+r)}, 'D':{'C': (1+r, 1-r), 'D': (0, 0)}}
    net = Net(30)
    # 博弈网络中边的集合
    edge_list = [(0, 1), (0, 2), (2, 3), (3, 4),  #节点边的定义
                (3, 15), (4, 14), (4, 19),
                    (5, 6), (6, 18), (7, 17),
                (8, 15), (8, 11), (9, 10),
                (10, 16), (12, 16), (12, 19),
                (13, 15), (14, 18), (17, 19),(1,21),(2,22),(3,23),(4,24),
                (5,25),(6,26)
                ,(8,27),(9,28),(10,29),(29,20)
                 ,(2,28),(11,26),(13,25),(18,29),(25,20)   ]
    net.buideNet(({net.nodes[a], net.nodes[b]} for a, b in edge_list))
    while net.updateState():
        continue
    net.printState()
    print(net.numbers)
    print(net.nodes[1].state)
point=[]
point1=[]
G=nx.Graph()
for i in range(net.numbers):
    if net.nodes[i].state=='C':
        point.append(i)
    else:
        point1.append(i)

G.add_nodes_from(point)

G=nx.Graph(edge_list)   #画网络图
position = nx.circular_layout(G)
nx.draw_networkx_nodes(G,position, nodelist=point, node_color="r")
nx.draw_networkx_nodes(G,position, nodelist=point1, node_color="g")
nx.draw_networkx_edges(G,position)
nx.draw_networkx_labels(G,position)  
plt.title("r=0.8,kmax=5")    
plt.show()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值