影响力最大化 IC模型+贪心算法

记录一下影响力最大化的遍历解决的方法,写的很粗糙,就是怕自己以后忘了,不喜勿喷。
一起共勉~~

贪心

(1)首先|S|=1,在所有点中选一个在IC模型下跑出感染的点数量最多的点加入S
(此时跑了n趟IC)
(2)再在剩下的点中选一个加入S后结果最好的点加入S
(此时跑了n-1趟IC)
(3)重复2,直到能S扩散的结果能覆盖所有点

IC

(1)激活S中的所有节点,加入活集A(本轮被激活的所有点)
(2)找到A的非活邻居集N(可能被传染的所有点),对于N中的每一个点,被传染的概率都为1-(1-Pa1,n)*(1-Pa2,n)…。
(3)清空A
(4)标记所有被传染的点,并放入A
(4)重复2、3直到步骤2已经不能找到新点

数据原型

处理的是一个txt文件,邻接矩阵表示的图。
在这里插入图片描述

代码

import numpy as np
import copy
import random


# IC模型
# 输入:图的邻接矩阵、初始节点集S
# 输出:感染点的个数
def ICModel(data, init_set) -> int:
    # 活集A,存储本轮被激活的所有点
    # 初始值为S
    active_set = init_set

    # 所有节点的激活状态
    # 0为未激活,1为激活
    active_status_set = np.zeros(len(data), dtype=int)

    # 激活所有起始点
    for index2 in range(len(init_set)):
        active_status_set[init_set[index2]] = 1

    # 开始循环
    while active_status_set.sum() < len(data):

        # A的非活邻居集N
        # 存储本轮可能被传染的点
        neighbor_set = []

        # 取出未激活可达点,及点的所有有效边的概率
        p_dictionary = {}
        for d_index in range(len(data)):
            for s_index in range(len(active_set)):
                # 可达且未被激活
                if data[active_set[s_index], d_index] != 0.0 and active_status_set[d_index] != 1:
                    if d_index not in neighbor_set:
                        neighbor_set.append(d_index)
                        p_dictionary[d_index] = []
                    p_dictionary[d_index].append(data[active_set[s_index], d_index])

        tmp = neighbor_set
        # 出口:不存在未激活可达点
        if len(neighbor_set) == 0:
            break

        # 计算未激活可达点的激活概率
        neighbor_p_set = []
        for index2 in range(len(neighbor_set)):
            p_one = p_dictionary[neighbor_set[index2]]
            p = 1.0
            for i in range(len(p_one)):
                p = p * (1 - p_one[i])
            p = 1 - p
            neighbor_p_set.append(p)

        # 清空A集
        active_set = []

        # 激活
        for index3 in range(len(neighbor_set)):
            seed = random.random()
            if seed < neighbor_p_set[index3]:
                active_status_set[neighbor_set[index3]] = 1
                active_set.append(neighbor_set[index3])

    # print(init_set, active_status_set)
    return active_status_set.sum()


# 验证random均匀分布
def test_rnd():
    r01 = 0
    r12 = 0
    r23 = 0
    r34 = 0
    r45 = 0
    r56 = 0
    r67 = 0
    r78 = 0
    r89 = 0
    r910 = 0

    for i in range(10000000):
        x = random.random() * 10
        if 0 <= x < 1:
            r01 += 1
        if 1 <= x < 2:
            r12 += 1
        if 2 <= x < 3:
            r23 += 1
        if 3 <= x < 4:
            r34 += 1
        if 4 <= x < 5:
            r45 += 1
        if 5 <= x < 6:
            r56 += 1
        if 6 <= x < 7:
            r67 += 1
        if 7 <= x < 8:
            r78 += 1
        if 8 <= x < 9:
            r89 += 1
        if 9 <= x < 10:
            r910 += 1

    print("******random()均匀分布验证结果******")
    print("0~1:", r01)
    print("2~3:", r12)
    print("3~4:", r23)
    print("4~5:", r34)
    print("5~6:", r45)
    print("6~7:", r56)
    print("7~8:", r67)
    print("8~9:", r78)
    print("9~10:", r910)


if __name__ == "__main__":


    # 读取图的关系矩阵
    graph_data = np.loadtxt('graph.txt')

    # 初始节点集
    init_set = []

    # 激活节点个数
    spread_num = 0

    print("**********贪心+IC@IM结果**********")

    # (贪心算法)往S中加入新节点,使得每次加入后激活的节点数最多
    # 当所有节点都被激活时停止循环
    # f = open('result.txt', 'a')
    while spread_num != len(graph_data):
        max_spread_num = 0
        for index in range(len(graph_data)):
            if index not in init_set:
                test_S = copy.deepcopy(init_set)
                test_S.append(index)
                result_spread_num = ICModel(graph_data, test_S)
                if result_spread_num >= max_spread_num:
                    max_spread_num = result_spread_num
                    max_spread_node = index
        spread_num = max_spread_num
        init_set.append(max_spread_node)
        print("init_num: ", len(init_set), " spread_num: ", max_spread_num, " S:", init_set)
        # f.write("init_num: " + str(len(init_set)) + " spread_num: " + str(max_spread_num) + " S:" + str(init_set) + "\n")

    # f.close()
发布了34 篇原创文章 · 获赞 36 · 访问量 4232

猜你喜欢

转载自blog.csdn.net/qq_40742298/article/details/104102274