编程语言
首页 > 编程语言> > 2022春季 哈工大 硕士算法设计与分析 实验三 近似算法

2022春季 哈工大 硕士算法设计与分析 实验三 近似算法

作者:互联网

 

 

 

 

 


贪心思想: 每次选取未覆盖元素最多的子集
线性规划思想: 以0-1线性规划解整数规划,将结果变量的取值大于1/f的对应子集放入C中 可证明C为可行解且近似比为f  
import random
import matplotlib.pyplot as plt
from pulp import *
import time
Numbers = None
X = []
F = []
Count = [100, 1000, 5000]
def DataProduct(Numbers):
    global X, F
    X = [i for i in range(Numbers)]
    random.shuffle(X)
    T = X.copy()
    S0 = [T[i] for i in range(20)]
    for i in range(20):
        T.pop(0)
    F.append(S0)
    while len(T) >= 20:
        Si = []
        # Si的length和从X剩余元素中取的length
        n = random.randint(1, 20)
        x = random.randint(1, n)
        # 从X剩余元素中取x放入Si中
        for j in range(x):
            # 随机下标
            idx = random.randint(0, len(T) - 1)
            Si.append(T[idx])
            T.pop(idx)
        # 从前一个集合中选n - x个元素
        Si_1 = F[-1]
        for j in range(n-x):
            idx = random.randint(0, len(Si_1) - 1)
            Si.append(Si_1[idx])
        F.append(Si)
    if len(T) > 0:
        F.append(T)
    y = len(F)
    idx = 0
    # 自己建立Number - len(F)个集合放入F
    for i in range(Numbers - len(F)):
        Si = [X[idx]]
        idx = idx + 1
        F.append(Si)
    return y

def Greedy(X, F):
    U = set(X)
    C = []
    while len(U) > 0:
        # S为F中与已覆盖元素没有交集的最大子集
        S = []
        maxn = 0
        for s in F:
            t = set(s)
            l = len(U & t)
            if l > maxn:
                maxn = l
                S = s
        # 从全集中删除S,并覆盖S(将S放入C)
        U = U - set(S)
        C.append(S)
    return C

def computer(X, F):
    prob = LpProblem("line", LpMinimize)
    # 为F中每个子集建立一个变量,这里只是变量名
    names = [str(i) for i in range(len(F))]
    # 变量字典,定义域[0, 1]
    x_vars = LpVariable.dicts("x",names,lowBound=0, upBound=1)
    # 默认F中每个子集权值为1
    prob += lpSum([x_vars[i] for i in names])
    f = 0
    for e in X:
        # 对X中的每个e判断在F的哪几个子集中,列出相应变量
        ve = [x_vars[i] for i in names if e in F[int(i)]]
        # f是X的元素在集族F中的最大频率
        if f < len(ve):
            f = len(ve)
        # >= 1保证了至少有一个有e的子集能被选中
        prob += lpSum(ve) >= 1
    prob.solve()
    return [v.varValue for v in prob.variables()], f

def LinePlan(X, F):

    C = []
    xs, f = computer(X, F)
    for i, x in enumerate(xs):
        if x >= 1.0 / f:
            C.append(F[i])
    return C

if __name__ == '__main__':
    greedy = []
    lp = []
    for Numbers in Count:
        DataProduct(Numbers)
        start = time.time()
        result = Greedy(X, F)
        end = time.time()
        greedy.append(end-start)
        start = time.time()
        result = LinePlan(X, F)
        end = time.time()
        lp.append(end-start)
    plt.plot(Count, lp, 'r.-', label='LinePlane')
    plt.plot(Count, greedy, 'y.-', label = 'Greedy')
    plt.ylabel('Time')
    plt.xlabel('Pointnums')
    plt.legend()
    plt.show()

 

标签:plt,idx,len,Si,哈工大,2022,time,append,近似算法
来源: https://www.cnblogs.com/WTSRUVF/p/16350519.html