日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

复杂网络作业六:Louvain社区发现算法原理,细节以及实现

發布時間:2023/12/10 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 复杂网络作业六:Louvain社区发现算法原理,细节以及实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 一、Louvain是什么?
  • 二、算法思路
    • 1.社區劃分的合理性
    • 2.算法流程
    • 3.ΔQ\Delta{Q}ΔQ的計算方式
  • 三、代碼實現
  • 總結


前言

這個第五題本身并不難,只是我個人對這個Louvain的算法比較感興趣。所以,就花的一周時間。可能是因為這是一篇算法型的論文吧。所以,復現難度不算太大。但是,如果不參考網上的一些已經寫完的代碼其實也會漏掉很多細節。包括現在也是并不確定我寫的是否是一定正確。每次更新之后也會在博客里同步更新。如果是你的目標是想要實現那就從一開始慢慢看,在這里有很多實現細節的說明和我個人的理解。如果要代碼就直接跳到最后 ,其實我也不能保證一定正確。畢竟這不是ACM的算法題能有一個準確的對錯。


一、Louvain是什么?

Louvain是一個用于社區發現的傳統算法。這個算法出現于2008年,那么什么是社區發現呢?舉個例子:假設我們有一個圖,在這個圖中的節點是某個鎮的所有的人,圖中的每一條邊代表的是兩個人之間的說話的數量。(現實生活中這個可能難以統計)而社區發現就是在這個圖中我們需要確定哪些人之間是一個團體,這個所謂的團體可能是同一個小學,也可能是同一個家庭或者是同一個小區等等。論文的原文全稱是:Fast unfolding of communities in large networks 作者:Vincent D. Blondel, Jean-Loup Guillaume, Renaud Lambiotte and Etienne Lefebvre

二、算法思路

1.社區劃分的合理性

作為一個認真的人,在放出公式之前先說明。論文中給出的用于衡量社區劃分合理性的公式并非是最好的。畢竟,十年都過去了,應該有其他的一些公式吧(我猜的)。但是,我能確定的是最好的一種劃分方式一定是真實結果(這句話看起來像句費話)。公式如下(其中的幾個乘號是我自己加上去的,我想應該不會錯。):
Q=12?m∑i,j[Aij?ki?kj2?m]δ(ci,cj)Q=\frac{1}{2*m}\sum_{i,j} [A_{ij} - \frac{k_i*k_j}{2*m}]\delta(c_i,c_j)Q=2?m1?i,j?[Aij??2?mki??kj??]δ(ci?,cj?)
mmm:如果是無向圖,圖中所有邊的權值和。如果是有向圖就是圖中所有邊的權值和的一半。論文中原本的寫法是m=12∑ijAijm = \frac{1}{2}\sum_{ij}A_{ij}m=21?ij?Aij?表面上看是圖中所有邊的一半。但是對于無向圖而言需要把每一條邊當作兩條有向邊來看。
AijA_{ij}Aij?:代表的是節點i和節點j之間的邊的權值。
kik_iki?:是所有指向節點i的邊的權值和。注意:就是這一個定義當我們在處理自環的時候就需要注意一個細節。假設有一個節點的圖案如下圖所示:

其中權值為4的邊是一個自環需要當作兩條邊來看,就上圖的i點而言其中的kik_iki?的值是28。
δ(ci,cj)\delta(c_i,c_j)δ(ci?,cj?):就是判斷i節點和j節點是否是同一個社區。如果是那么值就是1否則就是0
我這么寫可能是有此啰嗦。但是如果你能有耐心看完那么在實現的時候就能避開很多的坑。因為我這個可不是對論文的簡單翻譯。

2.算法流程

其算法流程一共有兩個大步驟,不斷的迭代往復。
1.我們先要把每一個單一的節點都看作是一個單獨的社區。對于每一個單一的節點,先要把它從它所在的社區中取出來。然后,再嘗試依次加入到它相鄰的社區中計算其收益ΔQ\Delta{Q}ΔQ。(ΔQ\Delta{Q}ΔQ的計算方法之后在詳細說,本文給出了三種不同的計算方法。)如果,最大的ΔQ\Delta{Q}ΔQ小于0則將它放回到原先的社區中,否則就加入到收益最大的那一個社區中。對所有的節點都不斷的循環反復的進行這一操作。直到所有節點的所處社區都不再發生變化。(不知道有沒有人和我一樣看原文的時候這一句沒看到。)
從這一步的做法中我主觀的感覺這個算法的目的是想要最大化Q的。但是,在實際情況中卻又不是Q越大就越接近真實劃分。詳情就要參考論文中的第12篇參考文獻了。(我沒有看過,詳細了解這個公式Q的同學可以說一下)
2. 通過第一步我們已經對圖有了一個新的社區劃分。于是在這一步中我們會對每一個社區都要把其中的對應的那些節點都縮成一個超節點,而這個超節點就代表了這一個社區中的若干個結點。而邊的處理方式與咱們的邏輯十分相符。如果一條邊連接的是同一個社區就把它變成對應超節點的一條自環邊,如果一條邊連接的是兩個不同的社區就讓這條邊連接兩個對應的超節點。然后計算一個新的全局Q值。如果這個Q值與之前的Q值相同那么就結束整個算法。(如果是第一次迭代那就不用考慮結束的事了)
為了能夠更加形象的理解,我試試看畫一個圖。
(假裝有圖,好吧我畫不出來。還是會的工具太少。)

3.ΔQ\Delta{Q}ΔQ的計算方式

在這一部分中我會一共會放三種不同的計算方式這三種方式都是基于一個大前提——我們需要嘗試將一個節點加入到社區C中。其中第一種是論文中給出的,第二種是其它的一些代碼中使用的版,(據說論文的初稿用的也是這個版本)第三種是我根據自己的理解推導得到的。(其正確性有待商榷,推薦使用第二種。)
1.ΔQ=[∑in+ki,in2?m?(∑tot+ki2?m)2]?[∑in2?m?(∑tot2?m)2?(ki2?m)2]\Delta{Q} = [\frac{\sum_{in}+k_{i,in}}{2*m} - (\frac{\sum_{tot} + k_i}{2*m})^2] - [\frac{\sum_{in}}{2*m}-(\frac{\sum_{tot}}{2*m})^2 - (\frac{k_i}{2*m})^2]ΔQ=[2?min?+ki,in???(2?mtot?+ki??)2]?[2?min???(2?mtot??)2?(2?mki??)2]
由于我個人對這個公式的理解并不完全,因此不對這個公式作非常詳細的解讀。僅僅只對其中的變量做一些簡單的解釋。
∑in\sum_{in}in?:社區C的內部的所有邊的權值和,注意:如果是無向圖則需要每一條邊看作是兩條有向邊,所以,是所有邊的權值和的兩倍。
ki,ink_{i,in}ki,in?:所有從節點i指向區域C的邊的權值和。
mmm:如果是無向圖,圖中所有邊的權值和。如果是有向圖就是圖中所有邊的權值和的一半。
∑tot\sum_{tot}tot?:所有指向區域C中的節點的邊的權值和。剛開始的時候,我把這個理解成了從區域C指向外面的所有邊的權值和。因此,踩了一個大坑。(這機種理解的區別就在于對自環的處理不同。)
kik_iki?:指向節點i的所有邊的權值和。(注意對自環的處理。)
在接下了我們就在這個公式的基礎上進行劃簡:
ΔQ=[∑in2?m+ki,in2?m?(∑tot2?m)2?(2?∑tot?ki4?m2)?(ki2?m)2]?[∑in2?m?(∑tot2?m)2?(ki2?m)2]=ki,in2?m?2?∑tot?ki4?m2=12?m?(ki,in?∑tot?kim)\Delta{Q} = [\frac{\sum_{in}} {2*m} + \frac{k_{i,in}}{2*m} - (\frac{\sum_{tot}}{2*m})^2 - (\frac{2*\sum_{tot}*k_i}{4*m^2}) - (\frac{k_i}{2*m})^2] - [\frac{\sum_{in}}{2*m}-(\frac{\sum_{tot}}{2*m})^2 - (\frac{k_i}{2*m})^2] \\ = \frac{k_{i,in}}{2*m} - \frac{2*\sum_{tot}*k_i}{4*m^2} \\ =\frac{1}{2*m}*(k_{i,in} - \frac{\sum_{tot}*k_i}{m})ΔQ=[2?min??+2?mki,in???(2?mtot??)2?(4?m22?tot??ki??)?(2?mki??)2]?[2?min???(2?mtot??)2?(2?mki??)2]=2?mki,in???4?m22?tot??ki??=2?m1??(ki,in??mtot??ki??)
在上述公式中12m\frac{1}{2m}2m1?在算法進行的過程中全程是一個常數,不會影響其大小的比較。因此在比較大小的過程中只需要比較(ki,in?∑tot?kim)(k_{i,in} - \frac{\sum_{tot}*k_i}{m})(ki,in??mtot??ki??)即可。
2.ΔQ=2?ki,in?∑tot?kim\Delta{Q}=2*k_{i,in} - \frac{\sum_{tot}*k_i}{m}ΔQ=2?ki,in??mtot??ki??
這個公式對應的上一個公式就是在ki,ink_{i,in}ki,in?前多了一個系數2,據說,作者剛發布的第一個版本的論文中用的就是這個后來修改了系數。同時用用使用這個公式作為ΔQ\Delta{Q}ΔQ的計算分割效果要更好一點。同時在karate的數據集中使用這個方法的效果確實比上一個公式的效果要更好一點。
3.這個是根據我自己的理解推出來的,但是它的正確性我無法驗證。我目前只用它在karate的數據集中運行過,不管是最終的Q值比前兩個方法的計算得到的Q值要更大一點。而目測效果與第二個相比相差不大。公式如下:
ΔQ=ki,in2?m?∑iki?f(i,j)?kj4?m2\Delta_{Q} = \frac{k_{i,in}}{2*m} - \frac{\sum_{i}{k_{i}*f(i,j)*k_{j}}}{4*m^2}ΔQ?=2?mki,in???4?m2i?ki??f(i,j)?kj??
其中f(i,j) 表示的是i,j之間是否有直接連邊。如果有則為1否則為0。

三、代碼實現

在給出我自己的實現代碼之前,先給大家另一個網站的實現方法。同時這個實現方法也是我在調試的過程中主要參考的一個代碼。放在前面是因為推薦大家使用這個,我想這個代碼的應該會比我自己實現的更準確吧。
1.code1
code轉載自:https://blog.csdn.net/weixin_40308540/article/details/101269508
(使用方法在最后面)

'''Implements the Louvain method.Input: a weighted undirected graphOuput: a (partition, modularity) pair where modularity is maximum '''class PyLouvain:'''Builds a graph from _path._path: a path to a file containing "node_from node_to" edges (one per line)'''@classmethoddef from_file(cls, path): #從txt中讀取一個netf = open(path, 'r')lines = f.readlines()f.close()nodes = {}edges = []for line in lines:n = line.split()if not n:breaknodes[n[0]] = 1nodes[n[1]] = 1w = 1if len(n) == 3:w = int(n[2])edges.append(((n[0], n[1]), w))# rebuild graph with successive identifiersnodes_, edges_ = in_order(nodes, edges)print("%d nodes, %d edges" % (len(nodes_), len(edges_)))return nodes_, edges_ #此處作了一點修改'''Builds a graph from _path._path: a path to a file following the Graph Modeling Language specification'''@classmethoddef from_gml_file(cls, path): #從gml中讀取一個netf = open(path, 'r')lines = f.readlines()f.close()nodes = {}edges = []current_edge = (-1, -1, 1)in_edge = 0for line in lines:words = line.split()if not words:breakif words[0] == 'id':nodes[int(words[1])] = 1elif words[0] == 'source':in_edge = 1current_edge = (int(words[1]), current_edge[1], current_edge[2])elif words[0] == 'target' and in_edge:current_edge = (current_edge[0], int(words[1]), current_edge[2])elif words[0] == 'value' and in_edge:current_edge = (current_edge[0], current_edge[1], int(words[1]))elif words[0] == ']' and in_edge:edges.append(((current_edge[0], current_edge[1]), 1))current_edge = (-1, -1, 1)in_edge = 0nodes, edges = in_order(nodes, edges)print("%d nodes, %d edges" % (len(nodes), len(edges)))return nodes, edges #此處作了一點修改'''Initializes the method._nodes: a list of ints_edges: a list of ((int, int), weight) pairs'''def __init__(self, nodes, edges):self.nodes = nodesself.edges = edges# precompute m (sum of the weights of all links in network)# k_i (sum of the weights of the links incident to node i)self.m = 0self.k_i = [0 for n in nodes]self.edges_of_node = {}self.w = [0 for n in nodes]self.orginer_network = []self.orginer_k_i = []for e in edges:self.m += e[1]self.k_i[e[0][0]] += e[1]self.k_i[e[0][1]] += e[1] # there's no self-loop initially# save edges by nodeif e[0][0] not in self.edges_of_node:self.edges_of_node[e[0][0]] = [e]else:self.edges_of_node[e[0][0]].append(e)if e[0][1] not in self.edges_of_node:self.edges_of_node[e[0][1]] = [e]elif e[0][0] != e[0][1]:self.edges_of_node[e[0][1]].append(e)# access community of a node in O(1) timeself.communities = [n for n in nodes]self.actual_partition = []self.orginer_k_i = []for k in self.k_i:self.orginer_k_i.append(k)'''Applies the Louvain method.'''def findRoot(self,node):for i,community in enumerate(self.actual_partition):if(node in community):return idef my_compute_modularity(self):sum_Q = 0for edge in self.orginer_network[1]:u,v = edge[0]w = edge[1]if(self.findRoot(u) == self.findRoot(v)):sum_Q = (w - (self.orginer_k_i[u]*self.orginer_k_i[v])/(2*self.m))/(2*self.m)return sum_Qdef apply_method(self):network = (self.nodes, self.edges)self.orginer_network = networkbest_partition = [[node] for node in network[0]]best_q = -1i = 1while 1:# print("pass #%d" % i)i += 1partition = self.first_phase(network)#q = self.compute_modularity(partition)q = self.my_compute_modularity()partition = [c for c in partition if c]# print("%s (%.8f)" % (partition, q))# clustering initial nodes with partitionif self.actual_partition:actual = []for p in partition:part = []for n in p:part.extend(self.actual_partition[n])actual.append(part)self.actual_partition = actualelse:self.actual_partition = partitionprint(q)if q == best_q:breaknetwork = self.second_phase(network, partition)best_partition = partitionbest_q = qreturn (self.actual_partition, best_q)'''Computes the modularity of the current network._partition: a list of lists of nodes'''def compute_modularity(self, partition):q = 0m2 = self.m * 2for i in range(len(partition)):q += self.s_in[i] / m2 - (self.s_tot[i] / m2) ** 2return q'''Computes the modularity gain of having node in community _c._node: an int_c: an int_k_i_in: the sum of the weights of the links from _node to nodes in _c'''def compute_modularity_gain(self, node, c, k_i_in):return 2 * k_i_in - self.s_tot[c] * self.k_i[node] / self.m'''Performs the first phase of the method._network: a (nodes, edges) pair'''def first_phase(self, network):# make initial partitionbest_partition = self.make_initial_partition(network)while 1:improvement = 0for node in network[0]:node_community = self.communities[node]# default best community is its ownbest_community = node_communitybest_gain = 0# remove _node from its communitybest_partition[node_community].remove(node)best_shared_links = 0for e in self.edges_of_node[node]:if e[0][0] == e[0][1]:continueif e[0][0] == node and self.communities[e[0][1]] == node_community or e[0][1] == node and \self.communities[e[0][0]] == node_community:best_shared_links += e[1]self.s_in[node_community] -= 2*(best_shared_links + self.w[node])#self.s_tot[node_community] -= self.k_i[node]self.s_tot[node_community] -= (self.k_i[node] - 2*best_shared_links)self.communities[node] = -1communities = {} # only consider neighbors of different communitiesfor neighbor in self.get_neighbors(node):community = self.communities[neighbor]if community in communities:continuecommunities[community] = 1shared_links = 0for e in self.edges_of_node[node]:if e[0][0] == e[0][1]:continueif e[0][0] == node and self.communities[e[0][1]] == community or e[0][1] == node and \self.communities[e[0][0]] == community:shared_links += e[1]# compute modularity gain obtained by moving _node to the community of _neighborgain = self.compute_modularity_gain(node, community, shared_links)if gain > best_gain:best_community = communitybest_gain = gainbest_shared_links = shared_links# insert _node into the community maximizing the modularity gainbest_partition[best_community].append(node)self.communities[node] = best_communityself.s_in[best_community] += 2*( best_shared_links + self.w[node])#self.s_tot[best_community] += (self.k_i[node])self.s_tot[best_community] += (self.k_i[node] - 2*best_shared_links)if node_community != best_community:improvement = 1if not improvement:breakreturn best_partition'''Yields the nodes adjacent to _node._node: an int'''def get_neighbors(self, node):for e in self.edges_of_node[node]:if e[0][0] == e[0][1]: # a node is not neighbor with itselfcontinueif e[0][0] == node:yield e[0][1]if e[0][1] == node:yield e[0][0]'''Builds the initial partition from _network._network: a (nodes, edges) pair'''def make_initial_partition(self, network):partition = [[node] for node in network[0]]self.s_in = [0 for node in network[0]]self.s_tot = [self.k_i[node] for node in network[0]]for e in network[1]:if e[0][0] == e[0][1]: # only self-loopsself.s_in[e[0][0]] += e[1]self.s_in[e[0][1]] += e[1]return partition'''Performs the second phase of the method._network: a (nodes, edges) pair_partition: a list of lists of nodes'''def second_phase(self, network, partition):nodes_ = [i for i in range(len(partition))]# relabelling communitiescommunities_ = []d = {}i = 0for community in self.communities:if community in d:communities_.append(d[community])else:d[community] = icommunities_.append(i)i += 1self.communities = communities_# building relabelled edgesedges_ = {}for e in network[1]:ci = self.communities[e[0][0]]cj = self.communities[e[0][1]]try:edges_[(ci, cj)] += e[1]except KeyError:edges_[(ci, cj)] = e[1]edges_ = [(k, v) for k, v in edges_.items()]# recomputing k_i vector and storing edges by nodeself.k_i = [0 for n in nodes_]self.edges_of_node = {}self.w = [0 for n in nodes_]for e in edges_:self.k_i[e[0][0]] += e[1]self.k_i[e[0][1]] += e[1]if e[0][0] == e[0][1]:self.w[e[0][0]] += e[1]if e[0][0] not in self.edges_of_node:self.edges_of_node[e[0][0]] = [e]else:self.edges_of_node[e[0][0]].append(e)if e[0][1] not in self.edges_of_node:self.edges_of_node[e[0][1]] = [e]elif e[0][0] != e[0][1]:self.edges_of_node[e[0][1]].append(e)# resetting communitiesself.communities = [n for n in nodes_]return (nodes_, edges_)'''Rebuilds a graph with successive nodes' ids._nodes: a dict of int_edges: a list of ((int, int), weight) pairs '''def in_order(nodes, edges):# rebuild graph with successive identifiersnodes = list(nodes.keys())nodes.sort()i = 0nodes_ = []d = {}for n in nodes:nodes_.append(i)d[n] = ii += 1edges_ = []for e in edges:edges_.append(((d[e[0][0]], d[e[0][1]]), e[1]))return (nodes_, edges_) ###################******************---下面是使用方法的一個例子---******************################### #下面是Louvain的使用方式 import argparse import networkx as nx import random import matplotlib.pyplot as plt def getRandomColor():'''這是隨機獲取一種顏色。但是,不能保證獲取的顏色差距一定很大。所以,如果想要直觀的看到結果。有時候需要多運行幾次。'''return random.randint(0,255) def drawNet_Louvain(G,part_list):'''將社區劃分完成的圖進行直觀的展示。'''for i in range(len(part_list)):for j in range(len(part_list[i])):part_list[i][j] += 1print(part_list)color_list = []for part in part_list:color = getRandomColor()for node in part:color_list.append((node,color))color_list.sort(key = lambda x: x[0])print(color_list)color_list = [x[1] for x in color_list]plt.figure(figsize=(5, 5))print("finish")print(len(G.nodes()))print(len(color_list))pos = nx.spring_layout(G)nx.draw(G, with_labels=True, node_color=color_list, pos=pos)plt.show()plt.savefig(r"filename.png")def main(option):data_path = option.data_path#此處需要修改對應的數據文件的路徑if (data_path[-3:] == "txt"): #如果文件是在txt中的讀取方式net_G_nodes,net_G_edges = PyLouvain.from_file(data_path) #使他的方法進行數據讀取,返回的是點集和邊集net_G = nx.read_edgelist(data_path) #因為他使用的是完全自己實現的代碼,無法進行畫圖展示。所以,需要自己在讀入一個networkx的elif (data_path[-3:] == "gml"): #如果文件是在gml中的讀取方式net_G_nodes,net_G_edges = PyLouvain.from_gml_file(data_path)#使他的方法進行數據讀取,返回的是點集和邊集net_G = nx.read_gml(data_path,label="id") #因為他使用的是完全自己實現的代碼,無法進行畫圖展示。所以,需要自己在讀入一個networkx的new_G = PyLouvain(net_G_nodes,net_G_edges) #使用它的方法構造成一個類,傳入的參數依次是點集和邊集t,d = new_G.apply_method() #應用其中的方法,對社區進行分割。返回值分別是最佳的社區劃分,以及對應的Q值。drawNet_Louvain(net_G, t) #對分割完成的圖進行展示。if __name__ == "__main__":parser = argparse.ArgumentParser()parser.add_argument("--data_path", type=str, default="karate.gml", help="data_path is the path of the net")opt = parser.parse_args()main(opt)

然后是我根據我自己的理解所實現的算法
2.code

import networkx as nx import argparsedef CalDeltaQ1(G,node_i,k_i_in,k_i,community_list,community_value,community_tot,community_id,neg_community_id,node_edge,edge_list,m,opt):'''function:用于計算deltaQparameter:G:當前的圖node_i:正在操作的節點的編號k_i_in:從i指向區域C的所有邊的權值和k_i:指向節點i的所有邊的權值和(包括自環的邊)community_list:每一個社區所包含的結點的編號community_value:社區內的所有這的權值和community_tot:社區指向外部節點的所有邊的權值和community_id :node_i 所處社區的編號neg_community_id:相鄰社區的社區編號node_edge:node_i這一節點的鄰邊edge_list:圖的所有邊的列表m:全圖的所有邊的和opt:其中有選擇deltaQ的計算方式的選項return:返回對應的deltaQ'''sumC = community_value[neg_community_id]sum_tot = community_tot[neg_community_id] + community_value[neg_community_id]if(opt.calDeltaQfunction == "fun_copy"): #使用的是參考代碼中的公式將其中的2改成1就是優化后的論文中的公式return 2*k_i_in - sum_tot*k_i/melif(opt.calDeltaQfunction == "my_fun"): #使用我自己推導的公式,因為沒有驗證過它的正確性。所以不推薦使用sum_k_i = 0delta_Q = (k_i_in)/(2*m)k_j = 0for edge in G[node_i]:if(edge in community_list[neg_community_id]):k_j += G.nodes[edge]["node_out"] + G.nodes[edge]["value"]delta_Q -= (k_j*k_i)/(4*(m**2))return delta_Qelse: #原模原樣的使用論文中的公式m2 = 2*mreturn ((sumC + k_i_in)/m2 - ((sum_tot + k_i)/m2)**2) - (sumC/m2- (sum_tot/m2)**2 - (k_i/m2)**2)def PutNode2Community(node,community_list,community_value,community_tot,k_i_c,k_i,root_id,m,level):'''使用并查集的方法進行編號合并parameter:node:結點 包涵信息root_id: 需要把結點加入的社區的idm:全圖的權值總合level:經過的第幾次合并(不知道怎么用)return:無,在過程中會更新node_list中的各個結點的root_list屬性值'''node["root_list"][0] = root_idcommunity_list[root_id].append(node["node_id"])community_value[root_id] += (node["value"] + 2*k_i_c)community_tot[root_id] += (k_i - 2*k_i_c)def getInitCommunity(G,node_list): #社區中所包涵的節點,社區value(sumC_in),社區的出度(sumC_tot)node2community = []node2community_value = []node2community_tot = []for node in node_list:node2community.append([node])node2community_value.append(G.nodes[node]["value"])node2community_tot.append(G.nodes[node]["node_out"])return node2community,node2community_value,node2community_tot def flag2Merge(G,node_list,m,level,opt):'''function :對接收的圖G進行社區劃分,返回劃分結果node_list:結點列表m :全圖的權值和level :迭代的次數opt :里面包含了deltaQ的計算方式return:社區劃分的表示形式。"set":每一個社區中所包含的節點的編號。"value":社區內部的權值。(社區內的邊的兩倍)"tot":社區內的節點指向,社區外的邊的和'''#對社區的信息進行初始化community_list,community_value,community_tot = getInitCommunity(G,node_list)while(True):promote = False #是否對于社區劃分是否有更新for node in node_list:#先將node結點移出node所對應的社區 可優化community_id = G.nodes[node]["root_list"][0] #該節點所屬的社區的編號community_list[community_id].remove(node) #將節點移出其所屬的社區k_i_c = 0 #從節點指向社區的所有邊的權值和for edge in G[node]:if(edge in community_list[community_id]):k_i_c += G[node][edge]["weight"]community_value[community_id] -= (2*k_i_c + G.nodes[node]["value"]) #由于已經將節點移出社區,所以需要更新其區社的value值community_tot[community_id] -= (G.nodes[node]["node_out"] - 2*k_i_c) #由于已經將節點移出社區,所以需要更新其區社的tot值#在相鄰的社區中找最優max_delta_Q = 0max_k_i_c = k_i_cbest_community_id = community_id#k_i = sum([edge["weight"] for edge in G[node].values()]) #原寫法k_i = G.nodes[node]["node_out"] #此處先把k_i 表示為該節點指向其它節點的邊的權值和#嘗試將節點加入到相鄰的社區之中neg_community_use = set()for neg_node in G[node]:if(isinstance(neg_node,int)):neg_community = G.nodes[neg_node]["root_list"][0] #相鄰節點所屬的社區if(neg_community in neg_community_use): #如果已經嘗試過則不再嘗試continueelse:neg_community_use.add(neg_community)k_i_c = 0 #節點相相鄰節點之間的權值和for edge in G[node]:if(edge in community_list[neg_community]):k_i_c += G[node][edge]["weight"]#計算deltaQdelta_Q = CalDeltaQ1(G,node,k_i_c,k_i + G.nodes[node]["value"],community_list,community_value,community_tot,community_id,neg_community,G[node],G.edges(),m,opt)#更新最優劃分,以及相關信息if(delta_Q > max_delta_Q):max_delta_Q = delta_Qmax_k_i_c = k_i_cbest_community_id = G.nodes[neg_node]["root_list"][0]#將節點加入到最優劃分的區間中if(max_delta_Q > 0 and best_community_id != community_id):promote = True#將節點加入到最優的社區中,并且更新其comuniyu的相關屬性PutNode2Community(G.nodes[node], community_list,community_value,community_tot,max_k_i_c,k_i,best_community_id, m, level)if(not promote):breakreturn {"set":community_list,"value":community_value,"tot":community_tot} def MergeG2getNewG(G,community):'''function:根據其社區劃分的結果重新生成一個新的圖G:原先的圖結構community:社區劃分的結果,community["set"]——社區中所包含的節點的編號community["value"]——社區內部的所有邊的權值和的兩倍community["tot"]——所有社區內部節點指向社區外部節點的邊的權值和return:返回一個縮點后的圖,以及其中對應的邊'''new_G = nx.Graph() #一個新的圖cnt_community = 0#對社區進行遍歷for i,community_set in enumerate(community["set"]): #將節點進行合并產生一批新圖中的總節點#node_id node_set root_list value outif(community_set): #如果在社區中有元素則構造新的節點,加入到圖中#編號i作為節點編號,community["set"]中的元素就是該社區所包含的對應的元素,將cnt_community作為臨時根,community["value"]作為該節點的編號,community["tot"]作為該節點的出度#community["value"] + community["tot"]就是指向該社區節點的所有邊的權值和new_G.add_node(i,node_id = i,node_set = community_set,root_list = [cnt_community],value = community["value"][i],node_out = community["tot"][i])cnt_community += 1for edge in G.edges(): #將邊進行處理加入到適當的新圖中#weightnode1,node2 = edgeroot1 = G.nodes[node1]["root_list"][0]root2 = G.nodes[node2]["root_list"][0]if(root1 == root2): #這條邊的一個社區的內部#在community["value"]中已經加上,所以不用在這里再加。在PutNode2Community函數中#new_G.nodes[root1]["value"] += 2*G[node1][node2]["weight"]continueelse:#這條邊的兩個社區之間,則與其它的邊一同進行合并if((root1,root2) not in new_G.edges()):new_G.add_edge(root1,root2,weight = G[node1][node2]["weight"])else:new_G[root1][root2]["weight"] += G[node1][node2]["weight"]return new_Gdef dealSelfLoop(G):'''對圖中的所有的邊進行遍歷,如果存在自環就將其刪除,同時一個自環就對那個對應的節點上的值+2問題:對于networkx 而言它會自動的刪除重邊。所以在這一點上對于使用networkx對最終的結果會有影響。'''for node in G:cnt_self_node = 0flag = Falsefor neg_node in G[node]:if(node == neg_node): #如果有重邊就刪除同時更新節點上的值flag = Truecnt_self_node += 2if(flag):G.remove_edge(node, node)G.nodes[node]["value"] = cnt_self_nodereturn Gdef stateINIT(G):for node in G:for edge in G[node]:G[node][edge]["weight"] = 1 #每一條邊都有一個權值,由于是無權圖因此權值都需要變為1for i,node in enumerate(G.nodes):G.nodes[node]["node_id"] = node #節點的IDG.nodes[node]["node_set"] = {node}#社區中所包含的節點(對于第一個圖用不上)G.nodes[node]["root_list"] = [i] #每一個節點從屬的社區的編號G.nodes[node]["node_out"] = sum([G[node][edge]["weight"] for edge in G[node]]) #節點相鄰邊的權值和def graphArrange(levelG_list):'''圖的整理,也就是根節點的向下傳遞更新每一層的圖的根節點'''l = -1*len(levelG_list) - 1for level in range(-2,l,-1):G1 = levelG_list[level + 1]G2 = levelG_list[level]for node in G1.nodes():#獲取節點的根,然后將該社區內的所有節點的根也進行更新root_id = G1.nodes[node]["root_list"][-1]# print(root_id,":")for member_id in G1.nodes[node]["node_set"]:# print(member_id,end=" ")G2.nodes[member_id]["root_list"].append(root_id)# print("")# print(G1.nodes())# print(G2.nodes())def calGraphQ(G,new_G,m,level,opt):'''function:計算圖在當前的社區劃分下的Q值G:原圖new_G:最近的經過縮點后的圖m:全圖的權值和level:遞歸的次數opt:其中指定了是使用哪一種Q的計算方法return:圖的Q值'''if(opt.calQFunction == "fun_copy"): #這是參考代碼中使用的Q的計算方式sum_Q = 0for new_node in new_G:sum_in = new_G.nodes[new_node]["value"]sum_tot = new_G.nodes[new_node]["node_out"]sum_Q += (sum_in/(2*m) - (sum_tot/(2*m))**2)return sum_Qelse: #這是在論文中使用的Q的計算方式sum_Q = 1for edge in G.edges:u,v = edgeroot_u = G.nodes[u]["root_list"][-1]root_v = G.nodes[v]["root_list"][-1]if(root_u == root_v): #如果u和v同屬于一個社區#G.nodes[u]["value"]節點內部的邊(自環)#G.nodes[v]["node_out"] 節點的鄰邊sum_u = G.nodes[u]["value"] + G.nodes[v]["node_out"]sum_v = G.nodes[v]["value"] + G.nodes[v]["node_out"]sum_Q -= sum_u*sum_v/(4*(m**2))*2 #乘二是因為(u,v)(v,u)要當作兩條邊來計算#sum_Q += (G[u][v]["weight"] - (sum_u)*(sum_v )/(2*m))/(2*m)return sum_Qdef Louvain(G,m,opt):dealSelfLoop(G) #對自環進行處理stateINIT(G) #對G添加屬性,同時完成初始化level = 0 #記錄迭代次數merageG_list = [] #在這個列表中用于記錄在迭代過程中的所有形成的子圖best_q = -2 #不斷更新,獲取最終的Q值while(True):level += 1#返回的是對圖的一個社區劃分,以及每一個社區中的信息#其中# community["set"]中存儲的是每一個社區中所包涵的結點的編號# community["value"] 中表示的是每一個社區的權值,其權值主要是自環的2倍# sommunity["tot"]中表示的是每一個社區內的結點指向外面的所有邊的權值和。(注意:此外不是指向所有社區內的所有邊的權值和)community = flag2Merge(G,list(G.nodes),m,level,opt)#將圖的社區劃分進行縮點重新組成一個新的圖,同時對于新的圖添加必要的信息new_G = MergeG2getNewG(G,community)#將新的圖添加到時圖列表中merageG_list.append(G)#將圖列表進行整理,只整理根節點的信息graphArrange(merageG_list)#重新更新使用的圖G = new_G#計算圖的Q值new_q = calGraphQ(merageG_list[0],G,m,level,opt)print(new_q)#如果Q值沒有變化則,線束算法if(new_q == best_q):break#更新最優的Q值(其實就是最后一種劃分的Q值)best_q = new_qreturn merageG_listdef CalGraphM1(net_G): #把單個邊當作無向圖的一條邊來處理#因為是無權所以邊的權值看作是1m = len(net_G.edges())return m import random import matplotlib.pyplot as plt def getRandomColor():return random.randint(0,255) def drawNet_Louvain(G_Louvain_list,show_level):"""function:將每一次迭代產生的社區劃分結果進行展示"""show_G = G_Louvain_list[0]#print(len(G_Louvain_list[show_level].nodes))color_list = []color_dict = {}for node in show_G.nodes():node_color = show_G.nodes[node]["root_list"][show_level]if(node_color in color_dict):color_list.append(color_dict[node_color])else:color = getRandomColor()color_dict[node_color] = colorcolor_list.append(color_dict[node_color])plt.figure(figsize=(5, 5))#print("finish")#print(len(show_G.nodes()))#print(len(color_list))pos = nx.spring_layout(show_G)nx.draw(show_G,with_labels=True,node_color=color_list,pos=pos)#plt.show()plt.savefig("filename" + str(show_level) + ".png")def main(option):data_path = option.data_pathif(data_path[-3:] == "txt"):net_G = nx.read_edgelist(data_path,comments='#',delimiter=None,create_using=None,nodetype=int,data=True,edgetype=int,encoding='utf-8',)elif(data_path[-3:] == "gml"):net_G = nx.read_gml(data_path,label="id")m = CalGraphM1(net_G) #計算全圖換邊權和G_merage_list = Louvain(net_G,m,option) #進行Louvain算法for i in range(len(G_merage_list)): #畫圖drawNet_Louvain(G_merage_list,i) if __name__ == "__main__":parser = argparse.ArgumentParser()parser.add_argument("--data_path",type = str,default="karate.gml", #數據的路徑help="data_path is the path of the net")parser.add_argument("--calQFunction",type = str,default="22", #計算Q的方式#Q的選擇只能是使用"fun_copy"或者其它,如果是"fun_copy"則使用的是code1中的Q的計算方法。如果是其它則使用的是原論文中的Q的計算方法help="calQFunction is the mode to calQ,should choose from ['fun_copy',other]") parser.add_argument("--calDeltaQfunction",type=str ,default="my_fun", #計算deltaQ的方式#deltaQ的選擇只能是使用"fun_copy"或者其它,如果是"fun_copy"則使用的是code1中的deltaQ的計算方法。如果是"my_fun"則使用的是我自己的理解推的一個公式。如果是其它則使用的是原論文中的deltaQ的計算方法help="calDeltaQfunction the mode to calDeltaQ,should choose from ['fun_copy','my_fun',other]")opt = parser.parse_args()#如果使用的是jupyter需要把上面一行注釋掉修改成下面這一行#opt = args = parser.parse_args(args=[])main(opt)

總結

我已經把我的代碼進行過更新了,暫時先這樣吧!效果也還算可觀。如果,之后有變化那就在更新。另外,好像第五題的第一題就是代碼(略)。第二題就是之前的東西(略)。第三題就是跑代碼(略)。第四題看情況吧,如果我做了我就一定會發博客。


因為一些原因在此添加數據的下載鏈接。(上面代碼使用的數據) 下載鏈接:http://www-personal.umich.edu/~mejn/netdata/ 數據名稱:Zachary's karate club 數據中的結點較少可以直接看到。

最后,如果有問題可以直接留言咨詢。如果我看到了,我一定會回復的

總結

以上是生活随笔為你收集整理的复杂网络作业六:Louvain社区发现算法原理,细节以及实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

欧美a视频| 最近中文字幕mv免费高清在线 | 又爽又黄又刺激的视频 | 天天操天操 | 欧美日韩3p | 亚洲一二三在线 | 深夜免费福利在线 | 国产美女网站在线观看 | 国产视频在线观看一区 | 日韩a级黄色 | 少妇资源站 | 久久精品超碰 | 久久精品男人的天堂 | 97国产小视频 | 国产精品免费麻豆入口 | 中文字幕精品在线 | 激情伊人 | 日本精品视频一区二区 | 开心激情综合网 | 欧美午夜久久久 | 视频国产在线 | 国产va精品免费观看 | 免费在线观看一区二区三区 | 在线日韩视频 | 国产99久久久久久免费看 | 久久国产亚洲 | 在线中文字幕电影 | 最近最新中文字幕视频 | 在线观看91| 永久免费观看视频 | 天天做日日做天天爽视频免费 | 国内久久 | www.精选视频.com | 97色国产 | 国产精品久久久久久久久久99 | 久久一线 | 亚洲人在线视频 | 免费观看福利视频 | 亚洲天天看 | 九九久久久久久久久激情 | 亚洲2019精品 | 亚洲国产网站 | 91麻豆精品国产91久久久使用方法 | 国内久久 | 夜夜操天天干 | 久久精品99北条麻妃 | 天天操天天操天天爽 | 国产午夜三级一区二区三 | 亚洲精品国产精品乱码不99热 | 欧美日韩中文在线观看 | 久久tv | 国产91成人在在线播放 | 在线观看第一页 | a v在线视频 | 国产三级视频在线 | 99久久精品费精品 | 黄网站色视频免费观看 | 日韩综合精品 | 免费看黄色毛片 | 日韩在线欧美在线 | 99视频免费在线观看 | 国产一区二区中文字幕 | 天天干天天操天天 | 中文字幕视频免费观看 | 最近免费中文字幕大全高清10 | 在线观看中文字幕视频 | 91亚洲狠狠婷婷综合久久久 | 久久综合九色欧美综合狠狠 | www.国产在线 | 亚洲永久精品在线 | 欧美精品在线免费 | 天天干天天怕 | 99久久爱| 欧美aa一级| 国产精品成 | 国产 欧美 日产久久 | 天天色天天射天天操 | 国产午夜精品久久久久久久久久 | 国产一区二区三区 在线 | 天天色成人 | 九色91福利| 欧美在线久久 | av资源免费在线观看 | av在线电影网站 | h视频日本| 婷婷色综 | 久草久 | 国产成人一级电影 | 国产视频精选 | 精品国内自产拍在线观看视频 | 国产精品美乳一区二区免费 | 精品国产美女 | 午夜精品一区二区三区视频免费看 | 91成人看片| 国产精品99久久久久久宅男 | 国产伦精品一区二区三区在线 | 国产亚洲午夜高清国产拍精品 | 欧美一级久久久 | 亚洲国产精久久久久久久 | 久久婷婷色综合 | 2018好看的中文在线观看 | 在线免费av播放 | 中文字幕一区二区三区四区久久 | 国产精品久久一卡二卡 | 国产精品视频免费观看 | 日本黄区免费视频观看 | 一本到视频在线观看 | 国产一区二区三区 在线 | 91在线观看视频 | 黄色福利| av网站免费线看精品 | 又色又爽又激情的59视频 | 91原创在线观看 | 久久伊人婷婷 | 91成人免费观看视频 | 五月天色丁香 | 日本久久视频 | 99视频导航 | 国产精品18毛片一区二区 | 永久免费的av电影 | 免费看一级 | 精品 一区 在线 | 色综合在 | 欧美一区二区三区在线视频观看 | 国产精品第 | av福利资源 | 国产成人精品一区一区一区 | 精品免费一区 | 国产 欧美 日本 | 国产精品久久艹 | 美女久久 | 久久影视网 | 婷婷久操| 日韩免费电影一区二区 | 久久久久国产免费免费 | 2023国产精品自产拍在线观看 | 欧洲高潮三级做爰 | 精品少妇一区二区三区在线 | 久久精品中文字幕一区二区三区 | 99国产情侣在线播放 | 久草网视频在线观看 | 免费视频一区 | 91精品国产乱码久久 | 在线播放你懂 | 欧美日韩视频免费看 | 天天做日日做天天爽视频免费 | 伊人一级 | 久久精品视频网 | 999成人网 | 国产xxxx做受性欧美88 | 96av麻豆蜜桃一区二区 | 丁香激情婷婷 | 免费观看的黄色片 | 中文字幕在线免费观看 | 天天射夜夜爽 | a在线观看免费视频 | h视频在线看| 特级黄录像视频 | 国产精品免费视频久久久 | 精品国产亚洲在线 | www亚洲国产 | 日韩免费观看av | 狠狠色香婷婷久久亚洲精品 | 美女网站在线免费观看 | 久久婷婷精品 | 色丁香久久 | 狠狠地日| 99在线视频精品 | 国产精品永久久久久久久久久 | 五月天激情视频在线观看 | 在线看不卡av | 久久久av电影 | 欧美激情综合色综合啪啪五月 | 99久久精品国产欧美主题曲 | 国产在线视频在线观看 | av免费电影在线 | 久久精品xxx| 亚洲久久视频 | 国产精品高清一区二区三区 | 久久99久久久久久 | 欧美最猛性xxxxx免费 | 草久电影| 日韩综合精品 | 国产精品中文久久久久久久 | 日本系列中文字幕 | 日韩精品一区不卡 | 国产视频在线看 | 97精品视频在线 | 免费高清在线观看成人 | 一二三区在线 | 美女免费视频黄 | 91成人网在线观看 | 国产看片网站 | 中文字幕在线免费观看 | 69国产盗摄一区二区三区五区 | 国产午夜在线观看 | 在线观看黄 | 在线观看视频97 | 国产亚洲亚洲 | 日韩av不卡在线播放 | 亚洲在线视频播放 | 黄网站a| 天天色欧美 | 日韩电影一区二区在线观看 | 日韩av在线免费看 | 亚洲日本在线视频观看 | 日韩欧美一区二区三区视频 | 中文字幕在线视频免费播放 | 精品中文字幕在线观看 | 久久五月天综合 | 亚洲国产精品女人久久久 | 久久久久成人精品亚洲国产 | 久久综合九色综合欧美狠狠 | 日韩高清在线一区二区三区 | 激情久久伊人 | 人操人| 成人毛片一区 | 欧美激情另类文学 | 日韩乱码在线 | 国产精品日韩在线观看 | 国产色影院| 2023av在线 | www.亚洲精品在线 | 91精品夜夜| 成人a视频片观看免费 | 亚洲小视频在线观看 | 国产免费视频在线 | 精品视频亚洲 | 射综合网| av在线精品 | 美州a亚洲一视本频v色道 | 黄色小说网站在线 | 久久久久久欧美二区电影网 | 亚洲欧美日韩精品久久久 | 午夜91在线 | 四虎成人在线 | 在线免费高清 | 波多野结衣视频一区二区 | 日韩久久久久久久久久 | av丝袜制服 | 国产美女免费观看 | 免费观看一区二区三区视频 | 五月婷婷在线观看视频 | 手机在线观看国产精品 | 欧美成年网站 | h网站免费在线观看 | 亚洲资源一区 | 亚洲免费av在线 | 久久免费视频2 | 色94色欧美 | 天天插天天狠天天透 | 999久久| 欧美夫妻性生活电影 | 香蕉视频在线播放 | 亚州国产精品视频 | 99精品免费久久久久久久久日本 | 青青河边草观看完整版高清 | 婷婷国产精品 | 色夜影院| 午夜av影院 | 中文字幕av在线不卡 | 热99在线视频| 亚洲伦理电影在线 | 久久综合五月 | 97av色| 国内成人精品视频 | 99综合视频| 久久黄色小说 | 丁香六月婷婷综合 | 激情综合六月 | 国产在线精品二区 | 久久综合九色综合久99 | 亚洲成免费| 波多野结衣综合网 | 成人综合婷婷国产精品久久免费 | 国产精品96久久久久久吹潮 | 成人免费观看大片 | 久久免费高清视频 | 日韩高清一区在线 | 成人久久久电影 | 久久视频免费在线 | 成人观看视频 | 国产精品99久久久久 | 国产视频久久久久 | 国产我不卡 | 456成人精品影院 | 在线高清 | 国产成人亚洲在线电影 | 在线观看视频你懂的 | 亚洲一区天堂 | 中文欧美字幕免费 | 久久综合给合久久狠狠色 | 久久免费激情视频 | 在线激情小视频 | av丝袜制服 | 中文字幕在线观看第三页 | 黄色日视频| 香蕉97视频观看在线观看 | 久久视频中文字幕 | 欧美日韩高清不卡 | 亚洲另类交 | 久久99在线 | 91视频免费网站 | 五月婷婷激情综合 | 久久久国产精品人人片99精片欧美一 | 91精品办公室少妇高潮对白 | 中文字幕网站视频在线 | 日韩中文字幕免费视频 | 人人玩人人爽 | 国产精品12 | 人人超碰免费 | 国产精品久久久久久久久久免费看 | 久久久久久久久久久久av | 国产一区二区三区免费在线 | 高清精品在线 | 精品福利网站 | 成年人黄色免费视频 | 欧美精品久久久久久久久免 | 黄色软件大全网站 | 热久久免费国产视频 | 中文字幕在线播放av | 97伊人网| 亚洲精品久久视频 | 激情久久久久 | 婷婷精品视频 | 国产黄色精品网站 | 亚洲 在线 | 日韩精品免费在线观看 | 手机av电影在线观看 | 日日夜夜精品视频天天综合网 | 亚洲电影av在线 | 网站免费黄色 | 国产精品99久久久久久小说 | 日本高清中文字幕有码在线 | 亚洲日本一区二区在线 | 欧美午夜a | 精品视频| 人人看人人爱 | 国产又粗又猛又色又黄视频 | 91九色视频在线观看 | 丁香 婷婷 激情 | 久久97久久97精品免视看 | 男女激情网址 | 久久久麻豆精品一区二区 | 狠狠干在线播放 | 在线黄频 | 午夜精品久久久久久久99无限制 | 日日摸日日碰 | 在线黄色国产 | 99c视频高清免费观看 | 97精品国产97久久久久久粉红 | 亚洲国产999 | 色干干| 日本久久免费视频 | 天天操天天射天天爽 | 亚洲91精品在线观看 | 午夜精品在线看 | 中文字幕日本在线 | 国产精品久久99综合免费观看尤物 | 精品成人国产 | 国产久视频 | 久保带人| 亚洲高清久久久 | 99在线精品视频观看 | 久久久精品网站 | 亚洲欧洲国产精品 | 日本精品在线 | 伊人狠狠干| 五月天婷婷免费视频 | 一区在线观看 | www在线观看视频 | 日韩免费成人av | 婷婷丁香狠狠爱 | 激情小说 五月 | 不卡的av中文字幕 | 最近中文字幕完整视频高清1 | 午夜久久久精品 | 黄色毛片视频免费观看中文 | 国产黄a三级三级三级三级三级 | 最近中文字幕大全中文字幕免费 | 一区二区三区免费看 | 精品二区视频 | 97av视频| 国产手机视频 | 日韩在线三级 | 久久黄色网页 | 免费av看片 | 日韩国产精品一区 | 色综合久 | 中文字幕第一页在线视频 | 精品国产乱码久久久久 | 九九涩涩av台湾日本热热 | 中文字幕观看av | 欧美亚洲xxx| 99免费视频 | 国产+日韩欧美 | 一区在线免费观看 | 国产精品9区 | 美女久久 | 国产一区二区精品久久91 | 国内精品久久久久久久影视简单 | 亚洲视频www | 亚洲粉嫩av | 日本成址在线观看 | 天天操天天干天天摸 | 夜夜操天天干 | 成人免费视频视频在线观看 免费 | 免费亚洲黄色 | 爱射综合| 五月婷婷六月丁香激情 | 天堂在线视频免费观看 | 久久久精品成人 | 国产视频一区在线播放 | 在线看av的网址 | 亚洲aⅴ乱码精品成人区 | 免费在线中文字幕 | 亚洲一区av | 午夜性生活 | 日韩视频在线不卡 | 青春草免费视频 | 日韩在线视频二区 | 天天色视频 | 日韩av黄 | 一级国产视频 | 国产精品国产三级国产专区53 | 色婷婷综合久久久久中文字幕1 | 欧美少妇xxxxxx | 成人黄色免费在线观看 | 国产福利电影网址 | 久久成人精品电影 | 婷婷av网站 | 99久久精品国产亚洲 | 久久精品人 | 97成人在线免费视频 | 黄a在线看| 在线观看免费版高清版 | 欧美日韩亚洲一 | 99精品在线| 中文字幕高清视频 | 国产高清网站 | 国产又粗又长的视频 | 808电影免费观看三年 | 国产精品一区二区在线观看 | 国产美女免费视频 | 伊人手机在线 | 日本中文字幕电影在线免费观看 | 激情伊人五月天 | 天天躁日日躁狠狠躁 | 伊人久久国产 | 国产一区高清在线 | 999抗病毒口服液 | 日韩av免费大片 | 欧美人体xx | 国产精品一区二区白浆 | 偷拍视频一区 | 成人精品影视 | 天天干天天操天天操 | av在线免费观看网站 | 久久久久97国产 | 麻豆视频在线观看免费 | 亚洲欧洲国产精品 | 午夜精品一区二区三区在线播放 | 日韩精品不卡 | 夜夜躁狠狠躁日日躁 | 午夜精品电影一区二区在线 | 九九久久精品视频 | www夜夜操com | 激情 婷婷 | 免费看片在线观看 | 狠狠干天天操 | 欧美成年黄网站色视频 | 久久久午夜剧场 | 国产一级在线视频 | 免费黄在线观看 | 国产拍在线 | 欧美精品一区二区三区一线天视频 | 999抗病毒口服液 | 香蕉视频在线看 | 日韩a在线播放 | 91视频 - v11av| 欧美精品九九99久久 | 四虎成人精品永久免费av九九 | 国产精品久久一卡二卡 | 亚洲综合色网站 | 在线免费av播放 | 夜夜天天干 | avwww在线观看 | 激情五月看片 | 精品99免费视频 | 久久国产精品久久精品 | 69国产成人综合久久精品欧美 | 99在线观看精品 | 欧美 另类 交 | 综合色天天 | 天天综合成人网 | 激情婷婷综合网 | 国产精品av久久久久久无 | 久久久久久久久久久久久影院 | 狠狠色免费 | 国产麻豆视频网站 | 日本二区三区在线 | 中文字幕在线专区 | 亚洲激情视频在线 | 成 人 黄 色 免费播放 | 国产人成精品一区二区三 | 久久精品一区二区三区中文字幕 | 99热这里精品 | 精品亚洲免费视频 | 日本三级中文字幕在线观看 | 久久成人高清 | 在线观看蜜桃视频 | 国产精品不卡在线播放 | 成人黄色av免费在线观看 | 五月婷婷.com | 久久99国产精品自在自在app | 岛国一区在线 | 中文免费 | 91看片在线观看 | 亚洲激情校园春色 | 国产伦精品一区二区三区四区视频 | 日韩在线观看中文字幕 | 网站在线观看你们懂的 | 国产一区二区中文字幕 | 久久久久国产一区二区三区四区 | 波多野结衣久久资源 | 麻豆视频免费观看 | 亚洲高清av| 狠狠躁18三区二区一区ai明星 | 福利视频一区二区 | 在线观看完整版 | 国产精品久久久网站 | 亚洲激情中文 | 久久久久国产精品免费网站 | 亚洲欧美综合精品久久成人 | 久久免费国产视频 | 香蕉视频导航 | 黄色在线观看污 | 综合色播 | 欧美性黑人| 精品国产一区二区三区久久久久久 | 天天色图| 91探花系列在线播放 | 色综合久久综合 | 日韩亚洲在线 | 在线播放视频一区 | 国产精品 美女 | 91成人在线免费观看 | 手机在线看a | 亚洲女同videos | 午夜在线免费观看视频 | 在线国产日本 | 欧美亚洲xxx| 中文字幕888 | 香蕉精品视频在线观看 | 日韩av高清 | 精品黄色片 | 亚洲另类久久 | 九草在线观看 | 亚洲精品一区二区三区高潮 | 欧美精品一区二区在线观看 | 色婷婷狠狠五月综合天色拍 | 午夜精品一区二区三区视频免费看 | 欧美淫aaa免费观看 日韩激情免费视频 | 久久综合色影院 | 国产成人一区二区啪在线观看 | 五月婷婷综| 免费在线观看成人av | 9999亚洲| 国产91在线免费视频 | 国产免费高清 | 日韩动漫免费观看高清完整版在线观看 | 9999精品视频 | 丝袜美腿在线播放 | 天天激情在线 | 2019国产精品 | 99视频免费看 | 91精品蜜桃| 五月婷香 | 亚洲国产经典视频 | 日本护士三级少妇三级999 | 精品一区二区三区香蕉蜜桃 | 黄色.com| 国产一区自拍视频 | 日韩理论在线观看 | 日本不卡视频 | 丁香在线观看完整电影视频 | 天天爽天天碰狠狠添 | 免费看成人a | 在线观看一区二区视频 | 久久精品国产免费看久久精品 | 日韩中文字幕在线看 | 免费看片在线观看 | 国产精品去看片 | 亚洲精品视频在线观看免费视频 | 国产精品亚洲视频 | 麻豆果冻剧传媒在线播放 | 日韩二区三区在线 | 免费一级特黄录像 | 久久久久久久久久久久影院 | 美女国产精品 | 久久精品欧美一区二区三区麻豆 | 手机色在线 | 欧美91精品国产自产 | 精品在线二区 | 中文字幕在线观看视频一区二区三区 | 91一区二区三区久久久久国产乱 | 美女搞黄国产视频网站 | 日韩超碰 | 日韩二级毛片 | 国产精品美女在线 | 99久久99久久精品国产片果冰 | 91精品在线播放 | 日韩在线观看视频一区二区三区 | 中文字幕.av.在线 | 91视频在线播放视频 | 欧美日韩国产mv | 手机在线永久免费观看av片 | av中文字幕不卡 | 亚洲午夜精品电影 | 亚洲电影久久 | 久久极品| 成人精品视频 | 中文字幕 在线看 | 人人干,人人爽 | 手机成人在线 | 婷婷av网站 | 五月婷婷.com| 国产99久久久国产精品 | 97人人人人 | 久久黄色影院 | 99精品视频免费观看视频 | 91免费高清观看 | 亚洲国产精品人久久电影 | 日日碰狠狠添天天爽超碰97久久 | 久久av中文字幕片 | 国产99久久久精品视频 | 国产第页 | 伊人色**天天综合婷婷 | 天天操天天摸天天干 | 国产成人精品av在线观 | 国产精品九九九九九九 | 午夜国产福利在线观看 | 91亚洲视频在线观看 | 在线高清| 丁香激情网 | 国产 成人 久久 | 丁香六月网 | 亚洲2019精品 | 亚洲天堂自拍视频 | 欧美日韩激情视频8区 | 久久黄色小说 | 亚洲精品综合欧美二区变态 | 超碰97免费 | 久久婷婷影视 | 久久精品视 | 国产午夜av | 日韩资源视频 | 97视频中文字幕 | 日韩免费观看视频 | 国产精品理论片 | 国产精品美女久久久久久久久久久 | 中文字幕一区二区在线观看 | 三级av网站| 在线日韩中文字幕 | 中文字幕免费中文 | 天天干,天天射,天天操,天天摸 | 亚洲综合射 | 成人av电影免费在线观看 | 亚洲少妇久久 | 激情视频91| 欧美日韩国产伦理 | 五月婷婷综合在线视频 | 久久久久久久影视 | 中文字幕在线免费观看视频 | 69国产盗摄一区二区三区五区 | 国产盗摄精品一区二区 | 免费看污片 | 麻豆mv在线观看 | 黄色aaa级片 | 99精品成人 | 正在播放国产精品 | 美女网站色在线观看 | 日韩理论视频 | 午夜免费视频网站 | 久久综合加勒比 | 国产精品久久久久久久久久妇女 | 久久精品久久精品久久39 | 国产色a在线观看 | 欧美精品久久久久久久久久白贞 | 五月天久久久 | 国产a视频免费观看 | 国产综合香蕉五月婷在线 | 麻豆精品视频在线 | 91欧美在线 | 国产最新91| 国产精品激情偷乱一区二区∴ | 久草在线中文888 | 91成人午夜 | 亚洲午夜久久久久久久久久久 | 国产精品嫩草影院99网站 | 精品国产1区 | 国产精品久久片 | 日韩中文字幕a | 久久久久免费精品国产小说色大师 | 亚洲三级精品 | 日本精品在线 | 激情五月婷婷丁香 | 国产黄色片免费在线观看 | 国产精品网站一区二区三区 | 最近中文字幕高清字幕免费mv | 国产精品一区专区欧美日韩 | 免费看片网页 | 四虎影视精品永久在线观看 | 在线久热| 在线国产中文字幕 | 日韩高清免费电影 | 亚洲黄色在线播放 | 国产成人精品一二三区 | 国产成人一区二区三区久久精品 | 国产午夜影院 | 国产成在线观看免费视频 | 麻豆视频免费在线观看 | 日韩高清在线看 | 国产精品久久久久免费观看 | 国产精品九九视频 | 96在线| 亚洲精品美女在线观看播放 | 久草在线视频在线 | 青青河边草免费视频 | 国产精品欧美日韩在线观看 | 中文字幕在线有码 | 免费在线成人av电影 | 日韩黄色影院 | 伊人狠狠色 | www.色五月 | 探花视频在线观看免费 | 国产一级性生活 | 久久精品久久精品久久39 | 日韩一区二区三免费高清在线观看 | 亚洲视频456| 欧日韩在线 | 日韩免费电影一区二区三区 | 成人黄色电影在线播放 | 亚洲最大成人免费网站 | 亚洲1区在线 | 天天干天天射天天插 | 日韩欧美精品在线观看视频 | 黄色毛片在线看 | 色婷婷激情网 | 国产精品久久久久久一区二区 | 六月丁香综合 | 在线看污网站 | 91av亚洲 | 日韩在线观看高清 | 一级电影免费在线观看 | 成人教育av | 欧美国产日韩一区二区 | 久久人人爽人人人人片 | 美女网站黄免费 | 91亚洲在线观看 | 97碰在线视频 | 欧美精品在线免费 | 亚洲永久字幕 | 日日夜夜天天射 | 久久日韩精品 | 人人干人人超 | 五月天,com | 久草在线资源观看 | 国产99免费视频 | 这里只有精品视频在线观看 | av电影在线观看完整版一区二区 | 在线综合 亚洲 欧美在线视频 | 中文字幕字幕中文 | 亚洲成人av电影在线 | 欧美激情视频一二三区 | 免费看一及片 | 日日日天天天 | 9在线观看免费高清完整版在线观看明 | 人人澡人 | 国产日韩欧美在线免费观看 | 麻豆免费精品视频 | 国产一区二区三区高清播放 | 成人精品国产免费网站 | 久艹视频免费观看 | 国产三级av在线 | 亚洲韩国一区二区三区 | 中文在线www | 激情片av | 久久国产成人午夜av影院潦草 | 国产精品18久久久久vr手机版特色 | 日韩一区二区三区免费电影 | 天天操天天干天天操天天干 | 成人久久视频 | 欧美午夜精品久久久久久孕妇 | 日韩欧美在线视频一区二区三区 | 色婷婷啪啪免费在线电影观看 | wwwwww国产 | 99色视频在线 | 婷婷国产一区二区三区 | 97超碰在线免费 | 久久不见久久见免费影院 | 午夜精品久久久 | 精品专区一区二区 | 午夜av激情 | 国产精品999久久久 久产久精国产品 | 操操碰 | 国产97免费 | 国产精品综合在线观看 | 亚洲播放一区 | 九九九九热精品免费视频点播观看 | 日本三级不卡视频 | 国产精品一区免费观看 | 在线观看视频你懂 | 国产97在线播放 | 天天久久综合 | 97视频久久久 | 日本成人中文字幕在线观看 | 一本大道久久精品懂色aⅴ 五月婷社区 | 五月婷婷黄色 | 伊人伊成久久人综合网小说 | 91麻豆精品久久久久久 | 国产视频 亚洲精品 | 日韩欧美国产视频 | 日本高清dvd | 色婷婷导航 | a√资源在线 | 九九热在线免费观看 | av色影院 | 成人av高清| 亚洲视频中文 | 精品久久91| 五月天激情电影 | 91av资源在线 | 久久短视频 | 日韩视频图片 | 九九视频网站 | 亚洲精品在线视频观看 | 欧美精品久久久久久久久久丰满 | 中文字幕亚洲精品在线观看 | 特级西西人体444是什么意思 | 四虎在线永久免费观看 | 香蕉成人在线视频 | 99热国产精品 | 91大神在线看 | 在线观看日韩精品视频 | 日韩在线网 | 国产在线观看 | 18做爰免费视频网站 | 国产免费av一区二区三区 | 日韩欧美视频一区二区三区 | 国产福利a | 国内精品久久久久影院日本资源 | 夜色在线资源 | 欧美在线视频一区二区三区 | 成人在线播放免费观看 | 中文字幕久久网 | 中文在线字幕免费观 | 97精品国产91久久久久久 | 在线观看精品一区 | 伊甸园永久入口www 99热 精品在线 | 成年免费在线视频 | 国产精品美乳一区二区免费 | 中文字幕在线网 | 色婷婷播放 | 天天操天天曰 | 国产亚洲精品久久久久久移动网络 | 日本精品视频在线播放 | 五月婷婷在线视频观看 | 中文字幕国语官网在线视频 | 天天操天天射天天爽 | 黄www在线观看 | 日日躁夜夜躁xxxxaaaa | 精品一区91 | 日韩有码欧美 | 手机在线看片日韩 | 人人玩人人爽 | 亚洲最新av| 男女啪啪视屏 | 国产69精品久久久久久久久久 | 天海翼一区二区三区免费 | 91香蕉视频色版 | 日韩在线视频网 | 天天色综合三 | 日韩试看 | 天天操天天玩 | 天天操天天舔天天爽 | 日本黄色免费电影网站 | 三级黄色三级 | 一区二区三区免费在线播放 | 在线观看黄色大片 | 六月丁香婷婷网 | 在线观看免费福利 | 国产爽视频| 一区二区三区在线观看中文字幕 | 日韩在线观看中文字幕 | 国产不卡一区二区视频 | 精品国产伦一区二区三区观看体验 | 亚洲精品乱码久久久久久蜜桃91 | 91精品一区二区三区蜜臀 | av网址aaa| 99久视频| 亚洲,播放 | 国产精品午夜av | 丁香婷婷综合激情五月色 | 日韩精品中文字幕在线播放 | 五月婷婷一级片 | 夜夜操天天摸 | 午夜影院三级 | 在线观看日韩专区 | 日韩欧美视频一区二区三区 | 99色人 | av动态图片 | 久久99最新地址 | 国产中文字幕在线观看 | 91爱爱网址| 日日草夜夜操 | 色婷婷国产精品一区在线观看 | 欧美男同网站 | 午夜精品福利一区二区 | 午夜精品一区二区三区四区 | 久久精品人 | 在线草 | 国产在线视频在线观看 | 国产免费一区二区三区网站免费 | 精品播放 | 91网站免费观看 | 国产理论在线 | 日韩久久片 | 超碰在线人人97 | 国产在线免费观看 | 黄色免费在线看 | 精品国产精品久久一区免费式 | 日韩在线播放视频 | 国产精品一区二区在线观看 | 99视频99| 婷婷深爱五月 | 久久久国产电影 | 亚洲成年人免费网站 | 国产黄大片在线观看 | 亚洲精品一区二区三区新线路 | 久久久久久久久久久久国产精品 | 99精品在线免费 | 婷婷国产一区二区三区 | 99中文字幕视频 | 特级黄色视频毛片 | 91在线91拍拍在线91 | 成人在线免费av | 天天干,天天射,天天操,天天摸 | 日韩精品一二三 | 亚洲综合小说电影qvod | 欧美小视频在线观看 | 成人国产精品一区 | 久久婷婷开心 | 999亚洲国产996395 | 日日夜夜天天干 | 国产精品成人久久久久久久 | 日本三级国产 | 久久色网站 | 又湿又紧又大又爽a视频国产 | 久久 一区| 97超碰精品 | 麻豆视屏 | av日韩国产 | 久久国产精品影片 | 国产精品手机视频 | 一区 二区电影免费在线观看 | 国产中文字幕在线视频 | 国内精品久久久久久 | 91资源在线播放 | 亚洲精品1区2区3区 超碰成人网 | 亚洲综合精品视频 | 欧美日韩在线视频一区二区 | 国产免费亚洲 | 日韩欧美99 | 91桃色免费观看 | 午夜黄色 | 麻豆免费视频观看 | 久草视频在线免费 | 黄色片网站av | av免费网站观看 | 欧美日韩精品电影 | 四虎永久国产精品 | 超碰在线人人97 | 中文字幕在线看视频国产中文版 | 国产成人精品一区二 | 日韩欧美网站 | 韩国精品一区二区三区六区色诱 | 欧美日韩亚洲第一页 | 2021国产在线视频 | 欧美美女视频在线观看 | 欧美有色 | 国产精品美女久久久免费 | 97在线资源| 国产99久久久欧美黑人 | 久久久午夜电影 | 国产一区在线免费观看 | 中文字幕日韩免费视频 | 中文字幕色播 |