前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【智能控制导论】雪堆博弈-最小节点覆盖问题

【智能控制导论】雪堆博弈-最小节点覆盖问题

作者头像
zstar
发布2022-06-13 08:54:57
8600
发布2022-06-13 08:54:57
举报
文章被收录于专栏:往期博文

本篇博文是智能控制导论专业课的实验报告 完整的程序和文档下载地址:https://download.csdn.net/download/qq1198768105/85259200

问题描述

验证结论:当雪堆博弈满足r<1/kmax时(kmax为网络节点的最大度),网络博弈的纳什均衡中的采用合作策略的节点构成极小节点覆盖。网络结构可自定,节点数目不少于10。

节点的初始状态可随机定为Cooperator或者Defector,按照某种给定顺序(例如1,2,…,10)依次检查每个节点,是否改变其状态可以获得更大收益,如果是则改变状态,否则不改变,直到所有节点都不再改变状态为止。验证合作的节点集合是否是极小节点覆盖。

问题背景

极小节点覆盖

网络节点最小覆盖问题(MVCP)是一个著名组合优化问题,其目的在于找出给定网络的最小节点集合以覆盖所有的边。其中,若节点集合中去掉任何一个点,就不能覆盖网络所有边,则称此时为极小节点覆盖。

雪堆博弈

雪堆博弈所描述的情景是:在一个风雪交加的夜晚,两人相向而来,被一个雪堆所阻。他们可以选择下车铲雪(合作C),或者都不铲雪(背叛D)。如果两人都不铲雪,两人就都无法通行;如果一人铲雪一人不铲,则铲雪者付出了劳动,背叛者白占了成果。

设铲雪所需的劳动价值为r,通行所获得的收益为1,则雪堆博弈的收益矩阵收益矩阵如下表所示

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

纳什均衡指的是在给定别人策略的情况下,没有人愿意单方面改变自己的策略,从而打破这种均衡。

算法思路

为了寻找到当前网络博弈的纳什均衡,需完成以下几个步骤:

  1. 随机给每个节点初始状态设置为C或D(C表示合作,D表示背叛)
  2. 依次对每个节点计算其采用C或者D的收益,改变其策略使其收益最大
  3. 重复2过程到每个节点的状态不在改变

算法流程如图1所示:

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

实验步骤

网络结构图

本实验网络设置了15个节点,其结构图如图2所示:

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

该网络中kmax为5,定理存在条件r<1/kmax,因此实验设定r为0.1。

第一次求解

首先初始化网络,每个节点都有50%的概率选择合作©或背叛(D),之后根据算法流程进行更新,初始状态,中间过程,最终结果如下图所示:

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

图中,红色代表决策C,白色代表决策D。可以发现,最终结果实现了极小节点覆盖。各节点的决策收益如表2所示:

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

第二次求解

第二次求解过程和第一次类似,初始状态,中间过程,最终结果如下图所示:

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

可以发现,由于初始生成情况较好,此次求解很快,中间状态和最终状态一致。同样,和第一次求解对比,可以发现极小节点覆盖的解不唯一,存在多解情况。各节点的决策收益如表3所示:

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

总结

本次实验验证了结论:当雪堆博弈满足r<1/kmax时(kmax为网络节点的最大度),网络博弈的纳什均衡中的采用合作策略的节点构成极小节点覆盖。与此同时,该验证过程还反映出个体在博弈中寻求最大利益的属性,会使得整个群体在数次迭代后趋向于一个对整体较为有利的情况,使得整个群体得到最大的利益。

参考文献

[1]吴建设, 焦李成, 皎魁,等.基于雪堆博弈进化的复杂网络节点覆盖方法:,CN105050096A[P]. 2015.

程序代码

python代码:

代码语言:javascript
复制
import random

# r<1/kmax
r = 0.1

# 收益矩阵
rewardMat = {
    'C': {'C': (1, 1), 'D': (1 - r, 1 + r)},
    'D': {'C': (1 + r, 1 - r), 'D': (0, 0)}
}


# 节点类,每个节点保存节点状态,邻居节点列表和邻居节点个数
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 printState(self):
        self.getAllReward()
        print('各个节点的决策和其收益:')
        for i in range(self.numbers):
            print('Noede%d:%c ==> reward: %f ' %
                  (i, self.nodes[i].state, self.nodes[i].value))
        print("博弈网络总体回报为:", self.reward)

    # 生成n个结点
    def initNode(self):
        for _ in range(self.numbers):
            tmp_node = Node()
            self.nodes.append(tmp_node)
            print(tmp_node.state)  # 打印初始状态

    # 根据传入的边的列表构建网络
    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):
            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'
                    continue
                flag = True
            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'
                    continue
                flag = True
        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]
        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__':
    net = Net(15)
    # 博弈网络中边的集合
    edge_list = [(0, 1), (0, 2), (0, 6), (0, 7),
                 (1, 2), (1, 4), (1, 9),
                 (2, 8), (2, 10), (2, 11),
                 (3, 5), (3, 12),
                 (4, 14),
                 (5, 13),
                 (6, 11), (6, 14),
                 (8, 9),
                 (12, 14)
                 ]

    net.buideNet(({net.nodes[a], net.nodes[b]} for a, b in edge_list))

    # 循环更新节点状态,直至每个人都不愿改变自己的决策
    while net.updateState():
        net.printState()  # 打印中间状态
    net.printState()
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述
  • 问题背景
    • 极小节点覆盖
      • 雪堆博弈
      • 算法思路
      • 实验步骤
        • 网络结构图
          • 第一次求解
            • 第二次求解
            • 总结
            • 参考文献
            • 程序代码
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档