• 作业分析,Karger最小割:(python)Engineering: Algorithms1


    Programming Assignment 3

    1/1 point (graded)

    Download the following text file (right click and select "Save As..."): kargerMinCut.txt

    The file contains the adjacency list representation of a simple undirected graph. There are 200 vertices labeled 1 to 200. The first column in the file represents the vertex label, and the particular row (other entries except the first column) tells all the vertices that the vertex is adjacent to. So for example, the 6th row looks like : "6 155 56 52 120 ......". This just means that the vertex with label 6 is adjacent to (i.e., shares an edge with) the vertices with labels 155,56,52,120,......,etc

    Your task is to code up and run the randomized contraction algorithm for the min cut problem and use it on the above graph to compute the min cut. (HINT: Note that you'll have to figure out an implementation of edge contractions. Initially, you might want to do this naively, creating a new graph from the old every time there's an edge contraction. But you should also think about more efficient implementations.) (WARNING: As per the video lectures, please make sure to run the algorithm many times with different random seeds, and remember the smallest cut that you ever find.) Write your numeric answer in the space provided. So e.g., if your answer is 5, just type 5 in the space provided.

    目前已经得到正确答案,把解决问题的思路记录一下:

    1,读取文件

    file = open("你的路径/kargerMinCut.txt",'r')
    dic = {}
    i = 1
    str = ''
    for line in file:
        dic[i] = []
        for char in line:
            if (char == "	" or char == "
    ") and str != "":
                dic[i].append(int(str))
                str = ""
            if char != "	" and char != "
    ":
                str += char
        i += 1
    
    for j in range(1,i):
        dic[j] = dic[j][1:]

    这里犯了个小错误:‘ ’ ‘ ’ 只是一个字符

    最后结果是把文件内容读到一个dict里面,key是node的名字1-200,value是一个list,存储图的连接信息。

    2,建立数据库

    为了避免每次运行代码都做一个新的图,这里我一共用了3个list同时更新:存储节点或者合并过的节点的archive,存储node是否在当前图里的activation,存储每个node的邻居的neighbor

    activation = []
    for j in range(len(dic)):
        activation.append(True)
    act_num = len(dic)
    ii = len(dic) + 1
    archive = []
    for j in range(1,ii):
        archive.append({j})
    neighbor = []
    for j in range(len(dic)):
        neighbor.append(dic[j+1])

    3,开始运行Karger算法

    3,1初始化几个变量

    act_num = len(activation)
    min_lib_element = 0
    min_lib = -1
    length = len(neighbor)

    act_num表示现在还剩下的有效node的个数,一开始是200

    min_lib_element表示这次循环的链接数结果

    min_lib表示目前运行过的循环,最小链接数结果

    length表示初始的长度,用于每次循环开始前的activation和act_num的初始化

    3,2随机选择两个nodes

    这里需要随机选node1和node2两个变量,形式是{1}或者{50,57,75,199}这样,

    首先看node1,从1-act_num随机选一个int出来叫index,然后到activation里面找第index个True的元素,对应在archive里面的元素就是node1

    然后看node1的neighbor,随机选一个出来,但这里选的neighbor不一定在activation里面对应True,所以需要循环activation表,找到坐标k,使得activation[k]为True,这个neighbor又在archive[k]里面,那么这个archive[k]就是node2

    其中找node1时候用到的函数如下:

    def find_true(activation,archive,index):
        i = 0
        for k in range(len(activation)):
            if activation[k] == True:
                i += 1
            else:
                continue
            if i == index:
                return archive[k]

    3,3如何处理nodes合并

    举个例子:

    node NO.1和node NO.2合并以后的

    archive:[{1},{2},{3},...,{200},{1,2}]

    activation:[False,False,True,...,True,True]

    neighbor前200个元素来自第一步的dic,后面需要写一个函数来计算任意两个nodes组合以后新的neighbor。当然,如果组合之后新的node已经在archive里面了,那就直接调用之前计算的结果。

    合并函数如下:

    def contract(node1,node2,archive,activation,act_num,neighbor):
        activation[archive.index(node1)] = False
        activation[archive.index(node2)] = False
        node_temp = node1|node2
        if node_temp not in archive:
            archive.append(node_temp)
            activation.append(True)
            combine_node(node1,node2,neighbor)
        else:
            activation[archive.index(node_temp)] = True
        for x in node_temp:
            activation[archive.index({x})] = False
        act_num -= 1
        return act_num

    如果这个组合是新的,那么需要在上面那个函数里嵌套使用这个函数来更新neighbor表:

    def combine_node(node1,node2,neighbor):
        same = list(node1)+list(node2)
        temp = []
        for n1 in node1:
            for nbr in neighbor[n1-1]:
                if nbr not in temp and nbr not in same:
                    temp.append(nbr)
                    
        for n2 in node2:
            for nbr in neighbor[n2-1]:
                if nbr not in temp and nbr not in same:
                    temp.append(nbr)
        neighbor.append(temp)

    3,4 循环

    for _ in range(你想循环的次数):
      
       #initialization
    for j in range(length): activation[j] = True for j in range(length,len(activation)): activation[j] = False act_num = copy.deepcopy(length)

      # 只要保持激活的节点还有2个以上,那就继续缩并节点
    while(act_num > 2): index = random.randint(1,act_num) node1 = find_true(activation,archive,index) pseudo_node2_index = random.choice(neighbor[archive.index(node1)])- 1 if activation[pseudo_node2_index] == True: node2 = archive[pseudo_node2_index] else: for k in range(len(activation)): if activation[k] == True and list(archive[pseudo_node2_index])[0] in archive[k]: node2 = archive[k] act_num = contract(node1,node2,archive,activation,act_num,neighbor) node = [] for k in range(len(activation)): if activation[k] == True: node.append(archive[k]) for n1 in node[0]: for n2 in node[1]: if {n1,n2} in libedge: min_lib_element += 1 if min_lib < 0: min_lib = min_lib_element elif min_lib_element < min_lib: min_lib = min_lib_element min_lib_element = 0
    #最后执行以下这个,看结果
    print(min_lib)

    结束!结果是17

    4,总结:

    做到后面发现用pandas来做,代码可能可以更精简

  • 相关阅读:
    用initconnect+binlog实现用户操作追踪【转】
    INSERT INTO … SELECT 的锁【转】
    Memcached 高可用方案 Repcached
    关于MySQL建表对DML的影响【转】
    NoSQL之【memcached】学习
    关于MySQL insert into ... select 的锁情况
    MySQL数据库诊断——InnoDB关机问题 【转】
    Your document is being created
    Failure to Get Sequential Numbering Profile Option
    Runtime error '1004'
  • 原文地址:https://www.cnblogs.com/ecoflex/p/9235130.html
Copyright © 2020-2023  润新知