From d74da8cdc578ffd12a537cf35d489b1cb28141f7 Mon Sep 17 00:00:00 2001 From: Lili Wang <569175789@qq.com> Date: Tue, 21 Sep 2021 22:51:56 -0400 Subject: [PATCH] Initial commit --- .gitattributes | 2 + barbell.pdf | Bin 0 -> 6532 bytes brazil2.out | 1 + data/barbell.edgelist | 101 + data/brazil-airports.edgelist | 1074 ++ data/europe-airports.edgelist | 5995 +++++++ data/karate-mirrored.edgelist | 156 + data/karate-mirrored2.edgelist | 155 + data/label_graph.py | 4 + data/labels-brazil-airports.txt | 132 + data/labels-europe-airports.txt | 400 + data/labels-usa-airports.txt | 1191 ++ data/relabel.py | 21 + data/usa-airports.edgelist | 13599 ++++++++++++++++ env.yml | 152 + europe2.out | 1 + evaluate_brazil.py | 75 + evaluate_europe.py | 75 + evaluate_synthetic.py | 75 + evaluate_usa.py | 75 + karate.pdf | Bin 0 -> 13118 bytes readme.txt | 35 + shapes/__init__.py | 11 + shapes/__init__.pyc | Bin 0 -> 371 bytes shapes/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 306 bytes shapes/__pycache__/build_graph.cpython-36.pyc | Bin 0 -> 6592 bytes shapes/__pycache__/shapes.cpython-36.pyc | Bin 0 -> 13622 bytes shapes/build_graph.py | 193 + shapes/build_graph.pyc | Bin 0 -> 7208 bytes shapes/shapes.py | 370 + shapes/shapes.pyc | Bin 0 -> 14384 bytes stress/__init__.py | 1 + stress/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 145 bytes stress/__pycache__/alias.cpython-36.pyc | Bin 0 -> 1067 bytes stress/__pycache__/classify.cpython-36.pyc | Bin 0 -> 3998 bytes stress/__pycache__/utils.cpython-36.pyc | Bin 0 -> 1186 bytes stress/__pycache__/walker.cpython-36.pyc | Bin 0 -> 7966 bytes stress/alias.py | 54 + stress/classify.py | 85 + stress/models/__init__.py | 3 + .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 188 bytes .../models/__pycache__/sm2vec.cpython-36.pyc | Bin 0 -> 10472 bytes stress/models/sm2vec.py | 413 + stress/utils.py | 48 + stress/walker.py | 276 + usa2.out | 1 + utils/__init__.py | 7 + utils/__init__.pyc | Bin 0 -> 169 bytes utils/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 172 bytes utils/__pycache__/utils.cpython-36.pyc | Bin 0 -> 2885 bytes utils/function_utils.py | 69 + utils/graph_tools.py | 53 + utils/graph_tools.pyc | Bin 0 -> 2593 bytes utils/utils.py | 73 + utils/utils.pyc | Bin 0 -> 2895 bytes varied.out | 4 + vis_barbell.py | 91 + vis_karate.py | 100 + 58 files changed, 25171 insertions(+) create mode 100644 .gitattributes create mode 100644 barbell.pdf create mode 100644 brazil2.out create mode 100644 data/barbell.edgelist create mode 100644 data/brazil-airports.edgelist create mode 100644 data/europe-airports.edgelist create mode 100644 data/karate-mirrored.edgelist create mode 100644 data/karate-mirrored2.edgelist create mode 100644 data/label_graph.py create mode 100644 data/labels-brazil-airports.txt create mode 100644 data/labels-europe-airports.txt create mode 100644 data/labels-usa-airports.txt create mode 100644 data/relabel.py create mode 100644 data/usa-airports.edgelist create mode 100644 env.yml create mode 100644 europe2.out create mode 100644 evaluate_brazil.py create mode 100644 evaluate_europe.py create mode 100644 evaluate_synthetic.py create mode 100644 evaluate_usa.py create mode 100644 karate.pdf create mode 100644 readme.txt create mode 100644 shapes/__init__.py create mode 100644 shapes/__init__.pyc create mode 100644 shapes/__pycache__/__init__.cpython-36.pyc create mode 100644 shapes/__pycache__/build_graph.cpython-36.pyc create mode 100644 shapes/__pycache__/shapes.cpython-36.pyc create mode 100644 shapes/build_graph.py create mode 100644 shapes/build_graph.pyc create mode 100644 shapes/shapes.py create mode 100644 shapes/shapes.pyc create mode 100644 stress/__init__.py create mode 100644 stress/__pycache__/__init__.cpython-36.pyc create mode 100644 stress/__pycache__/alias.cpython-36.pyc create mode 100644 stress/__pycache__/classify.cpython-36.pyc create mode 100644 stress/__pycache__/utils.cpython-36.pyc create mode 100644 stress/__pycache__/walker.cpython-36.pyc create mode 100644 stress/alias.py create mode 100644 stress/classify.py create mode 100644 stress/models/__init__.py create mode 100644 stress/models/__pycache__/__init__.cpython-36.pyc create mode 100644 stress/models/__pycache__/sm2vec.cpython-36.pyc create mode 100644 stress/models/sm2vec.py create mode 100644 stress/utils.py create mode 100644 stress/walker.py create mode 100644 usa2.out create mode 100644 utils/__init__.py create mode 100644 utils/__init__.pyc create mode 100644 utils/__pycache__/__init__.cpython-36.pyc create mode 100644 utils/__pycache__/utils.cpython-36.pyc create mode 100644 utils/function_utils.py create mode 100644 utils/graph_tools.py create mode 100644 utils/graph_tools.pyc create mode 100644 utils/utils.py create mode 100644 utils/utils.pyc create mode 100644 varied.out create mode 100644 vis_barbell.py create mode 100644 vis_karate.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/barbell.pdf b/barbell.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a732657213153df88ea5df065f3b8b3e1f4d3eae GIT binary patch literal 6532 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 bO^AHawEEZ$>So#(f4KAC$&*d;#2VfoI%r9f literal 0 HcmV?d00001 diff --git a/shapes/__pycache__/__init__.cpython-36.pyc b/shapes/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bee4f3502cb4ceddafc2dd356d363db64f15e6f GIT binary patch literal 306 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�_!Mv2%cP-3qSMJrrbOK3yfHX1G4K zcY;TGz*Mjx%)C^xfh z%!%~8;zZ&@GAmfW*+HTNR?R(s$o`d8I_%jMpW{pbs-Q*tSL1yuTY(J0eFQ589MUF1 zEFZi4oM}Lf!_J;AtbTug-R+S;v{sGD4hbQ+Hi!4Xx<#N38vz_>LrS}edo9=45J049wXcQXA%PH~ov&wxAj5!M zRd51AfxNQYL_LJ!pq_Gc@#b&t3JZn+!iVl_8-{#8Z}2_0a_jvYG!i(xpa{ZvpdB%| z#mXG;mj_UJ1g@R)8DdN`_qbA4&mdaV%bUW2irQLIzIyaRVMVuo4zMC%35Le6q4e2^ zawUH}uB`Mq!7l;MqtGDb9t8D9;SVYJvV_y2h*zOOWrZ>}D3hUTN`^yz`bYZ63o5};p*7bMkDQo6s$V{_Z ziE@>mO{)m2Ep}n5wW<_%W0c7iD#?li$u=H6c1*ZFc{>V=2K_d@1*sU?0tLgI)-C*< zVEvrJE?vXp^a8w=tW?}Y$v(X`9V9O+xj7DsfkCZ*qGiT90#*cEB}m!#;Q+y(`H6W? zy9c)k$KJb{GkHdm^%MP`e$T*D`d0}zYh;$H$5NLaDSH}%C!2`Pr*jK|mZ(KahHyW% z@I+gmp%MZC!ky;3g}Ihw6C0^o4m4^~g?KqUhXjXToxny7oILln`>+ovOfxq=6NY6@ zVu}lW8d_@S}iIyi-7s8qxa` z$}||GOT1~$rYIJ>f}HY;T}SIEsr2{jrL*kOR~?~;lTtc2QB^)!G`d}p^t;{S7^1mp zNkpR_BI7AlIO-}x^jf&%7;QC2Hs){Zj+$dT?T?WD3mV*6I$fa?#o|cX@aJtwN!tmM z9GvVKlVoGFy}){pBoOn1: + args += shape[1:] + args += [0] + graph_s, roles_graph_s = eval(shape_type)(*args) + n_s = nx.number_of_nodes(graph_s) + try: + col_start = seen_shapes[shape_type][0] + except: + col_start = np.max(role_id) + 1 + seen_shapes[shape_type] = [col_start, n_s] + # Attach the shape to the basis + basis.add_nodes_from(graph_s.nodes()) + basis.add_edges_from(graph_s.edges()) + basis.add_edges_from([(start, plugins[shape_id])]) + role_id[plugins[shape_id]] += (-2 - 10 * seen_shapes[shape_type][0]) + communities += [shape_id] * n_s + temp_labels = [r + col_start for r in roles_graph_s] + temp_labels[0] += 100 * seen_shapes[shape_type][0] + role_id += temp_labels + start += n_s + + if add_random_edges > 0: + # add random edges between nodes: + for p in range(add_random_edges): + src, dest = np.random.choice(nx.number_of_nodes(basis), + 2, replace=False) + print (src, dest) + basis.add_edges_from([(src, dest)]) + if plot is True: plot_networkx(basis, role_id) + + return basis, communities, plugins, role_id + + +def build_lego_structure(list_shapes, start=0, plot=False, savefig=False, + bkbone_graph_type='nx.connected_watts_strogatz_graph', + bkbone_graph_args=[4, 0.4], save2text='', add_node=10): + '''This function creates a graph from a list of building blocks on top + of a backbone graph + INPUT: + --------------------------------------------------------------------------------- + list_shapes : list of shape list (1st arg: type of shape, + next args: args for building the shape, except + for the start) + bkbone_graph_type : which type of backbone graph + (default= 'nx.connected_watts_strogatz_graph') + add_nodes : number of "empty nodes" to add to the graph structures, ie, + nodes in the graph that do not belong to a + particular clique + bkbone_graph_args : arguments for generating the backbone graph + (except from nb of nodes, which + is automatically computef) + start : initial node nb + plot, savefig,save2txt: plotting and saving parameters + + OUTPUT: + --------------------------------------------------------------------------------- + graph : a nx graph (association of cliques/motifs + planted along a backbone structure) + communities : motif Id + role_labels : role id + label_shape : label/class of the motif. This induces + different levels of similarities among motifs + ''' + graph = nx.Graph() + shape_id = [] # labels for the different shapes + role_labels = [] # labels for the different shapes + communities = [] # roles in the network + seen_shapes = {} + + start = graph.number_of_nodes() + for nb_shape, shape in enumerate(list_shapes): + shape_type = shape[0] + try: + role_start, shape_id_start = seen_shapes[shape_type] + except: + if len(role_labels) > 0: + seen_shapes[shape_type] = [np.max(role_labels) + 1, np.max(shape_id) + 1] + role_start, shape_id_start = seen_shapes[shape_type] + else: + seen_shapes[shape_type] = [0, 0] + role_start, shape_id_start = 0, 0 + args = [start] + args += shape[1:] + args += [role_start] + graph_s, roles = eval(shape_type)(*args) + # Attach the shape to the basis + graph.add_nodes_from(graph_s.nodes()) + graph.add_edges_from(graph_s.edges()) + + communities += [nb_shape] * nx.number_of_nodes(graph_s) + role_labels += roles + shape_id += [shape_id_start] * nx.number_of_nodes(graph_s) + start += graph_s.number_of_nodes() + # Now we link the different shapes by attaching them to the underlyin + # graph structure: + n_nodes, n_shapes = graph.number_of_nodes(), len(list_shapes) + graph.add_nodes_from(range(n_nodes, n_nodes + add_node)) + role_labels += [n_shapes + 1] * add_node + communities += range(n_shapes, n_shapes + add_node) + shape_id += [-1] * add_node + + # generate back_bone Graph + bkbone_graph_args.insert(0, n_shapes + add_node) + bkbone_graph = eval(bkbone_graph_type)(*bkbone_graph_args) + for e in bkbone_graph.edges(): + ii = np.random.choice(np.where(np.array(communities) == e[0])[0], 1)[0] + jj = np.random.choice(np.where(np.array(communities) == e[1])[0], 1)[0] + graph.add_edges_from([(ii, jj)]) + + if plot is True: plot_networkx(graph, role_labels) + if len(save2text) > 0: saveNet2txt(graph, colors=role_labels, name='net', path=save2text) + return graph, communities, role_labels, shape_id + + +def create_bigger_network(nb_cells, width_cell, list_cell_shapes, + rdm_basis_plugins=True, cell_type="cycle"): + ''' Automatically creates a big network by linking several instances of a + graph created by build_structure(width_basis, basis_type, list_shapes,..) + ''' + width_basis, basis_type = width_cell[0] + list_shapes = list_cell_shapes[0] + graph, roles, plugins = build_structure(width_basis, basis_type, + list_shapes, start=0, + rdm_basis_plugins=rdm_basis_plugins, + add_random_edges=0, plot=False) + start = graph.number_of_nodes() + for i in range(1, nb_cells): + width_basis, basis_type = width_cell[i] + list_shapes = list_cell_shapes[i] + graph_i, roles_i, plugins_i = build_structure(width_basis, + basis_type, + list_shapes, + start=start, + add_random_edges=0, + plot=False) + graph.add_nodes_from(graph_i.nodes()) + graph.add_edges_from(graph_i.edges()) + graph.add_edges_from([(start, start + 1)]) + start += graph_i.number_of_nodes() + roles += roles_i + plugins += plugins_i + return graph, roles, plugins diff --git a/shapes/build_graph.pyc b/shapes/build_graph.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f85109ea63422d247abe018307ac2dfccf41023 GIT binary patch literal 7208 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 0: + lst = np.random.choice(len(edge_list), nb_to_remove, replace=False) + print((edge_list, lst) ) + to_delete = [edge_list[e] for e in lst] + graph.remove_edges_from(to_delete) + for e in lst: + print ( edge_list[e][0]) + print ( len(roles)) + roles[edge_list[e][0]] += 1 + roles[edge_list[e][1]] += 1 + mapping_graph = {k: (k + start) for k in range(nb_nodes)} + graph = nx.relabel_nodes(graph, mapping_graph) + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def cycle(start, len_cycle, role_start=0, plot=False): + '''Builds a cycle graph, with index of nodes starting at start + and role_ids at role_start + INPUT: + ------------- + start : starting index for the shape + role_start : starting index for the roles + plot : boolean -- should the shape be printed? + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + role_start) + ''' + graph = nx.Graph() + graph.add_nodes_from(range(start, start + len_cycle)) + for i in range(len_cycle-1): + graph.add_edges_from([(start + i, start + i + 1)]) + graph.add_edges_from([(start + len_cycle - 1, start)]) + roles = [role_start] * len_cycle + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def diamond(start, role_start=0, plot=False): + '''Builds a diamond graph, with index of nodes starting at start + and role_ids at role_start + INPUT: + ------------- + start : starting index for the shape + role_start : starting index for the roles + plot : boolean -- should the shape be printed? + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + role_start) + ''' + graph = nx.Graph() + graph.add_nodes_from(range(start, start + 6)) + graph.add_edges_from([(start, start + 1), (start + 1, start + 2), + (start + 2, start + 3), (start + 3, start)]) + graph.add_edges_from([(start + 4, start), (start + 4, start + 1), + (start + 4, start + 2), (start + 4, start + 3)]) + graph.add_edges_from([(start + 5, start), (start + 5, start + 1), + (start + 5, start + 2), (start + 5, start + 3)]) + roles = [role_start] * 6 + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def fan(start, nb_branches, role_start=0, plot=False): + '''Builds a fan-like graph, with index of nodes starting at start + and role_ids at role_start + INPUT: + ------------- + nb_branches : int correspondingraph to the nb of fan branches + start : starting index for the shape + role_start : starting index for the roles + plot : boolean -- should the shape be printed? + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + role_start) + ''' + graph, roles = star(start, nb_branches, role_start=role_start) + for k in range(1, nb_branches - 1): + roles[k] += 1 + roles[k + 1] += 1 + graph.add_edges_from([(start + k, start + k + 1)]) + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def hollow(start, role_start=0, plot=False): + ''' Creates a torus-like basis structure where the + index of nodes start at start + and role_ids at role_start + INPUT: + ------------- + start : starting index for the shape + role_start : starting index for the roles + plot : boolean -- should the shape be printed? + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + ''' + graph1, _ = cycle(start, 5) + graph, _ = cycle(start + 5, 10) + graph.add_nodes_from(graph1.nodes()) + graph.add_edges_from(graph1.edges()) + graph.add_edges_from([(start, start + 5), (start + 1, start + 7), + (start + 2, start + 9), (start + 3, start + 11), + (start + 4, start + 13)]) + graph.add_edges_from([(start + 6, start + 1), (start + 6, start)]) + graph.add_edges_from([(start + 8, start + 2), (start + 8, start + 1)]) + graph.add_edges_from([(start + 10, start + 3), (start + 10, start + 2)]) + graph.add_edges_from([(start + 12, start + 4), (start + 12, start + 3)]) + graph.add_edges_from([(start + 14, start), (start + 14, start + 4)]) + roles = [role_start] * nx.number_of_nodes(graph) + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def house(start, role_start=0, plot=False): + '''Builds a house-like graph, with index of nodes starting at start + and role_ids at role_start + INPUT: + ------------- + start : starting index for the shape + role_start : starting index for the roles + plot : boolean -- should the shape be printed? + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + role_start) + ''' + graph = nx.Graph() + graph.add_nodes_from(range(start, start + 5)) + graph.add_edges_from([(start, start + 1), (start + 1, start + 2), + (start + 2, start + 3), (start + 3, start)]) + graph.add_edges_from([(start, start + 2), (start + 1, start + 3)]) + graph.add_edges_from([(start + 4, start), (start + 4, start + 1)]) + roles = [role_start, role_start, role_start + 1, + role_start + 1, role_start + 2] + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def karate_club(plot=False): + ''' + Defines the mirrored- Karate network structure ( KDD paper) + ''' + graph1 = nx.karate_club_graph() + a = nx.adjacency_matrix(graph1) + n_graph = nx.number_of_nodes(graph1) + b = np.zeros((n_graph, n_graph)) + a = np.bmat([[a.todense(), b], [b, a.todense()]]) + graph = nx.from_numpy_matrix(a) + # add link between two random members + roles = range(n_graph) + roles += range(n_graph) + graph.add_edges_from([(0, 36)]) + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def mirrored_cavemen(n, k, plot=False): + '''Builds a mirrored_cavemen graph + INPUT: + ------------- + n : number of nodes + k : number of cliques + plot : boolean -- should the shape be printed? + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + role_start) + ''' + n_graph = n * k + a = np.ones((k, k)) + np.fill_diagonal(a, 0) + adj = sc.linalg.block_diag(*([a] * n)) + for i in range(n-1): + adj[(i + 1) * k - 1, (i + 1) * k] = 1 + adj[(i + 1) * k, (i + 1) * k - 1] = 1 + adj[n * k - 1, 0] = 1 + adj[0, n * k - 1] = 1 + graph = nx.from_numpy_matrix(adj) + roles = [0] * n_graph + for i in range(n-1): + roles[(i + 1) * k - 1] = 1 + roles[(i + 1) * k] = 1 + roles[0] = 1 + roles[n * k - 1] = 1 + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def star(start, nb_branches, role_start=0, plot=False): + '''Builds a star graph, with index of nodes starting at start + and role_ids at role_start + INPUT: + ------------- + nb_branches : int correspondingraph to the nb of star branches + start : starting index for the shape + role_start : starting index for the roles + plot : boolean -- should the shape be printed? + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + role_start) + ''' + graph = nx.Graph() + graph.add_nodes_from(range(start, start + nb_branches + 1)) + for k in range(1, nb_branches + 1): + graph.add_edges_from([(start, start + k)]) + roles = [role_start + 1] * (nb_branches + 1) + roles[0] = role_start + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def string(start, width, role_start=0): + '''Builds a stringraph graph, with index of nodes starting at start + and role_ids at role_start + INPUT: + ------------- + start : starting index for the shape + width : int correspondingraph to the lengraphth of the stringraph + role_start : starting index for the roles + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + role_start) + ''' + graph = nx.Graph() + graph.add_nodes_from(range(start, start + width)) + for i in range(width - 1): + graph.add_edges_from([(start + i, start + i + 1)]) + roles = [role_start] * width + roles[0] = role_start + 1 + roles[-1] = role_start + 1 + return graph, roles + + +def tree(start, nb_levels, regularity, role_start=0, plot=False): + ''' Defines a clique (complete graph on nb_nodes nodes, + with nb_to_remove edges that will have to be removed), + index of nodes starting at start + and role_ids at role_start + INPUT: + ------------- + start : starting index for the shape + nb_levels : int correspondingraph to the nb of levels in the tree + regularity : nb of children for each node + role_start : starting index for the roles + plot : boolean -- should the shape be printed? + OUTPUT: + ------------- + graph : a house shape graph, with ids beginning at start + roles : list of the roles of the nodes (indexed starting at + role_start) + ''' + graph = nx.Graph() + nodes_level = [regularity**l for l in range(nb_levels)] + graph.add_nodes_from(range(start, start + np.sum(nodes_level))) + a = start + it = 0 + for n in range(1, np.sum(nodes_level)): + graph.add_edges_from([(a, start + n)]) + it += 1 + if it == (regularity): + a += 1 + it = 0 + + n = nx.number_of_nodes(graph) + roles = [role_start + 1] * nx.number_of_nodes(graph) + roles[0] = role_start + for i in range(regularity**l): + roles[n - 1 - i] += 1 + if plot is True: plot_networkx(graph, roles) + return graph, roles + + +def plot_networkx(graph, role_labels): + cmap = plt.get_cmap('hot') + x_range = np.linspace(0, 1, len(np.unique(role_labels))) + coloring = {u: cmap(x_range[i]) for i, u in enumerate(np.unique(role_labels))} + node_color = [coloring[role_labels[i]] for i in range(len(role_labels))] + plt.figure() + nx.draw_networkx(graph, pos=nx.layout.fruchterman_reingold_layout(graph), + node_color=node_color, cmap='hot') + plt.show() + return diff --git a/shapes/shapes.pyc b/shapes/shapes.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c53d48f82267f4ce18d9b461002765b926fd8a34 GIT binary patch literal 14384 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 XU#dTk&*l21+S%Gm^^3Ko`m4VLdSO6T literal 0 HcmV?d00001 diff --git a/stress/__init__.py b/stress/__init__.py new file mode 100644 index 0000000..cf4f59d --- /dev/null +++ b/stress/__init__.py @@ -0,0 +1 @@ +from .models import * \ No newline at end of file diff --git a/stress/__pycache__/__init__.cpython-36.pyc b/stress/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d243bfa4e5de20229ccdcd780ad7f868bc41e3a GIT binary patch literal 145 zcmXr!<>gv6i8Vo#fq~&M5W@izkmUfx#XLYFg&~D8harR^g(;XplldhhP)L*U7NeFQ zkYvlvPf5)wUdd3z0u%-lztr_J@^e%5b24)>^_~4)T;q+6P0jR+ONvs9i}mBh($ literal 0 HcmV?d00001 diff --git a/stress/__pycache__/alias.cpython-36.pyc b/stress/__pycache__/alias.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..efc27b396d5bd5ebecc11320438d10a1c63005e1 GIT binary patch literal 1067 zcmY*YKX21O6u*CVZ8xo;s!EF(G62F7B0zy5Dp0BIz*2?|m7=0>Jh<&2a*bWfMWj~GSL12TLEVg2&$nSpmGho71C&iYb@{(YrG1z8c9%1 zYC1$i1RATo3Xh1*v^ljueO^)R&+sn#@bHM#3w59aLB1k&q}hn+g&D@^cw2jO{SZx4 z&D1aL0kM%cLl6ZH)x$c{z798#COX_gI?~ihUq>5A0FI5V!w<9w;*H;;{d8!NLrWdn zr4DH8fOOGd)Dcu6_U^HP$X(68W7TS2QHL%DxW|7F?F;B<0)1nr@1m#;r(1Bvvo=?f z_Z6>_akpJgvPW|}e*LUTRI-|=yxZo3fh?-WJWY7%BFZ*@2n6Ti?YXsL-_TU%hUA6u zxKjMYgfgFG5+J1Uc~Qt*7+Q>rc(E7F!3<6z>Hy%LMKE5O@iaAF%GFTz7U#KrgA>CF zHU88KT~0p{(_ZNEta^sjEqKbm`<*Z2Om@;FO*%X8clY|6n=fB=%1X(y>^O`k#fe!N zKnE(>caDC=Kc&*{QTY@Y@&mkvBfN}PaDZE6nM9zqK=+-r9^XcQY+S9toq=6qdpsZt zrje!_2$tZ5rUyu4YaPJ)!tluH-p%2;hIMbu z)AsJtb2Ye9t^)YaTu;U&VQ|(os@DlgRN{VCaHX5_o%dw I3TW`)KRIgo8vpOxTzFjLdhm($&+&*eL(cUM-rU;WMh z(?7b5{gW*`9_n}T=>ZDC1TWZ-$DC8$DV*5B-!0ss7kfiL_HDmc1j8^6ZQU=TVJGfz z_AwKI2#=WvWjJ%=F4~dkpxu#6XfKNuu_Ts{dAuT=hpe~yHTGjYZdS)CA5}?zGRmsF z9Nq6ZChEVJ=&V%ItfpBuQEB#~X@mUgCnNcL{XpvKUXf~@_j9SJ`*)L~%72^g%i>r0 zC{_89R2l8iKJL7t-$F&QmTnRwSRE|c{!O;Y2GNX7Bf;yiq1}T9>adRXSnUlubvT1op5FZ2?p%8_PQ2b% z9K3u@MXzi8(PTJ&VZv0WN~JH1uP0-vRESZtGFDRLS(S`cxu2Sj1g%tQB~6r(B&AL; zQ61<~RVJv)BG>q*~4_sNI9PIh;H`oWH_l+=31lI8su+jNpS(@Qvk zUPrP9}yLOpx|@O?6K&YZRYB z;46BZDlL<8QjI4SB+`|`eJMmfI?#^ahFpR1E7Jkl zNcT%Mv_kCp%}&In;g4hgaRQey;iJSZ*K%jMAx4aE`)?2r5ef!dU&nW}cAk?HGa)k4 zhBcGts5Hh`J657VDG~?d?Myw?`Cu+xGEFke18?f*Y#KbjQTxEHjcEvEb0GClgsw)MET$o~aVQlzyR3hvPzO6a87{2Tv*~ z;3{GI3`lq&jf-$|boJefPcN`wVKuCN0yY#`vLeef06_$>UUaHr^)3z4d1L2s5=Zmp zwFv=mh*Me-N}M~PiP~e3k?QLx7~pN$z8*Ym1FZAQl0lP zidAqCXW$|>Il_HSc0tk4yQsbY$hWNiR1e!;a4)OFU5vCkd}l$2bL75Eg;Q3FAQ6d(cRX82hDx3_^ zy6YN&=_^iPdInA#)M^}7eFxNVUYcpH=qHnYAMrLHA>oj^F?6c|^5S3MYb{`RLHc@J zAg);8OIoA8%pA_3%YVnN_0v7@bB@J3r!4*tcO&7bOLqI^|7Ev-b+)^wyY-f>N0|V@ zN|Zy>IgnMNE6NF7K$^M@QcC=!FiXfIhZ77TMMqYM34lxA{?rbUb#yyd{T%Jy(m6Pc zR~pU2&oha&@6sgSZZ;o6Vv=ae+qW?khmRXmFad%jvi&$f2mX!Kxz^GeH@6Zc>oV6a zGohbh#AXJJcbzq$=?1@!_XfY=5V{_{{clY0J|M)V*O8)ltlp+#i;7!R(BbWgn*i}K zHBVEflhi`}00ZPCn&2yPB0mbE)yTK~A7zxr&_kIzVYiLq6)Fgnh~$Xc4sI6B?c&p# ztF77@@EJqIwg0J)`-OApsP{i*wNKzQK+;K&RJ*vF1j5?{K!Mt`E!;)E#65(1o?iQ$ z*6{6GZte9ONHAO(_J(iSlPk(CdV%pu+yzXeWGae$1ocB3`4~TPT=gvw89ysZEqfuZ za5=&`67aaA5A$*I1d}K=8Z9X9J(}S@li7m6tRAn>7Rjg-vbj}|Q0=`9Dn$76xPy;E zVT9T$-VM~$L*kNuL}_$_>tr=i$oLgWwz2Xn`mm6x8f_0H_|Eic2#?oKhUgZV(RD}> zvY2nT129`$X#i##W@?k>CWj8n{ejFXt47Pg!dXs~Z=${C26BfCNw1<4;)C0rk2jqF0{ML%oeMeO-%4F z@SiaHC(YFp|AHsKZ;C*Si3byR^S<-uN8Y^o%$xN_qyFu4`1VV{*mrjA6Y#fSW(A^{ z;-AR;Y@qqLnJzW35_`V<~+h4Dr}D%xpmtR`Nb8h2o{0tXg)&&e#rn z^Pmi@wA==p%!(tlXPh%Dm3YcZd9t*RQOgenV$0oggkk5jLrb_Y%~Wh$rJLt*s#>87 z`?{MCTtwq*iJG_wvPL~uBkh>vL+k=_zcO7%lpibYK{krp!(^DWw_onO=&Y|l*=UsgHT2poM8>=MF9bP8tK z8CU!cv%CqQ%K!o>5*8>?hLatD;U3Jh*P^VHRT~@$Td~zc;lYH8159W`E0%B-$3m}K zi4`6jMLAjBr(Mv;Y@qGctd$<3rsTATD4iU}sSA@L9vMxEwjvju#=1ywSXX_Q>El=% zS3l?$y}^`UE$`~0GfYh30&-p0%f@Np#OY%v(*xtdPGtrG-5f1SiX=-rD(Mx3$21{~ zFJ7Qq-~?|L_@=6tG5aqF3r>(xTmJ*0ZXjD%i_`Ha*4-k$z^HFvSW|`QntDiDVIoD=#UyxmsdABDeGP09M literal 0 HcmV?d00001 diff --git a/stress/__pycache__/walker.cpython-36.pyc b/stress/__pycache__/walker.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b84675aaa66f6ee7c1759185c8bf2fbe7d0f91fd GIT binary patch literal 7966 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 d`$mDIZeo*#U1V-Ecj^BG+^i`)_1L9ku`f literal 0 HcmV?d00001 diff --git a/stress/alias.py b/stress/alias.py new file mode 100644 index 0000000..a1eb094 --- /dev/null +++ b/stress/alias.py @@ -0,0 +1,54 @@ +import numpy as np + + +def create_alias_table(area_ratio): + """ + + :param area_ratio: sum(area_ratio)=1 + :return: accept,alias + """ + l = len(area_ratio) + accept, alias = [0] * l, [0] * l + small, large = [], [] + area_ratio_ = np.array(area_ratio) * l + for i, prob in enumerate(area_ratio_): + if prob < 1.0: + small.append(i) + else: + large.append(i) + + while small and large: + small_idx, large_idx = small.pop(), large.pop() + accept[small_idx] = area_ratio_[small_idx] + alias[small_idx] = large_idx + area_ratio_[large_idx] = area_ratio_[large_idx] - \ + (1 - area_ratio_[small_idx]) + if area_ratio_[large_idx] < 1.0: + small.append(large_idx) + else: + large.append(large_idx) + + while large: + large_idx = large.pop() + accept[large_idx] = 1 + while small: + small_idx = small.pop() + accept[small_idx] = 1 + + return accept, alias + + +def alias_sample(accept, alias): + """ + + :param accept: + :param alias: + :return: sample index + """ + N = len(accept) + i = int(np.random.random()*N) + r = np.random.random() + if r < accept[i]: + return i + else: + return alias[i] diff --git a/stress/classify.py b/stress/classify.py new file mode 100644 index 0000000..eb2bc67 --- /dev/null +++ b/stress/classify.py @@ -0,0 +1,85 @@ +from __future__ import print_function + + +import numpy +from sklearn.metrics import f1_score, accuracy_score +from sklearn.multiclass import OneVsRestClassifier +from sklearn.preprocessing import MultiLabelBinarizer + + +class TopKRanker(OneVsRestClassifier): + def predict(self, X, top_k_list): + probs = numpy.asarray(super(TopKRanker, self).predict_proba(X)) + all_labels = [] + for i, k in enumerate(top_k_list): + probs_ = probs[i, :] + labels = self.classes_[probs_.argsort()[-k:]].tolist() + probs_[:] = 0 + probs_[labels] = 1 + all_labels.append(probs_) + return numpy.asarray(all_labels) + + +class Classifier(object): + + def __init__(self, embeddings, clf): + self.embeddings = embeddings + self.clf = TopKRanker(clf) + self.binarizer = MultiLabelBinarizer(sparse_output=True) + + def train(self, X, Y, Y_all): + self.binarizer.fit(Y_all) + X_train = [self.embeddings[x] for x in X] + Y = self.binarizer.transform(Y) + self.clf.fit(X_train, Y) + + def evaluate(self, X, Y): + top_k_list = [len(l) for l in Y] + Y_ = self.predict(X, top_k_list) + Y = self.binarizer.transform(Y) + averages = ["micro", "macro", "samples", "weighted"] + results = {} + for average in averages: + results[average] = f1_score(Y, Y_, average=average) + results['acc'] = accuracy_score(Y,Y_) + print('-------------------') + print(results) + return results + print('-------------------') + + def predict(self, X, top_k_list): + X_ = numpy.asarray([self.embeddings[x] for x in X]) + Y = self.clf.predict(X_, top_k_list=top_k_list) + return Y + + def split_train_evaluate(self, X, Y, train_precent, seed=0): + state = numpy.random.get_state() + + training_size = int(train_precent * len(X)) + numpy.random.seed(seed) + shuffle_indices = numpy.random.permutation(numpy.arange(len(X))) + X_train = [X[shuffle_indices[i]] for i in range(training_size)] + Y_train = [Y[shuffle_indices[i]] for i in range(training_size)] + X_test = [X[shuffle_indices[i]] for i in range(training_size, len(X))] + Y_test = [Y[shuffle_indices[i]] for i in range(training_size, len(X))] + + self.train(X_train, Y_train, Y) + numpy.random.set_state(state) + return self.evaluate(X_test, Y_test) + + +def read_node_label(filename, skip_head=False): + fin = open(filename, 'r') + X = [] + Y = [] + while 1: + if skip_head: + fin.readline() + l = fin.readline() + if l == '': + break + vec = l.strip().split(' ') + X.append(vec[0]) + Y.append(vec[1:]) + fin.close() + return X, Y diff --git a/stress/models/__init__.py b/stress/models/__init__.py new file mode 100644 index 0000000..d55637f --- /dev/null +++ b/stress/models/__init__.py @@ -0,0 +1,3 @@ +from .sm2vec import SM2Vec + +__all__ = ["SM2Vec"] diff --git a/stress/models/__pycache__/__init__.cpython-36.pyc b/stress/models/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7b72d8742e3158c46cf1a790d27dd0621a4c0ab GIT binary patch literal 188 zcmXr!<>d;Q!O1?pxW*eBo0{ntmlUNI7whNdr=;c->&M4u=4F<|$LkeT-r}$U3YO-i+JS5= J2HC^I1OO7PDslh- literal 0 HcmV?d00001 diff --git a/stress/models/__pycache__/sm2vec.cpython-36.pyc b/stress/models/__pycache__/sm2vec.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..45c171b2c61096821ad2b7a7c5a7a2690c955b5c GIT binary patch literal 10472 zcmcIqTZ|l6TCRInS6^m4GoFh*NybUmNt<@^8B=Sn5-pT1-Nn*O4u{hM~+&qVrVJkgIpgeLTs=4Wr+*Hzx| z4ZMw(*|vPEZTq&K)jNJp)w_NkZ?omKJ>OGxR;$o1`bCwtTcvi{FSn=sDV29x)9q=0 z8tI&HTgTcn{)|fJTeIysf3AJpKd$m#YrehUFQ`6+*5WnJS!gYd-Y2eUpVLH9l?ydM@1iQ{7aj_yAq7Q`Y-R>YDxf%hqKQY_>BsL-!! zm4_eT>$UZYk-D$k2pXN&gI;QjaC;}L=xMGVM6rl(A?aT4O0o84SYyjK0vWVgVJppv zuoc`61sYiKwrD>vFc>m3H5mqRSPfc@Agac}Mk_?Waxai^BW`p%Rne%$=}b?CJ=v{= zQB>{pH)YVffxgAhqE9HU2d%A8BCnsRaf#zU4~duYM17D@<5A(5P76;I@UfDra`4|A($}LKUGIZCnsF+SOXn zs;Oq@s-2y7l{_RP-Kyt;99`2LeOjM0 z9K0P;qpTNo3s2G5oywSQb=<2)M&h51XTnr7$lyrHSVm$F&4HCz*^%n$a<$fN_jVwg zSkg`{-hm`fcBo>@C($=8w}bwHgOL>!$}=QSknlS*@-$PYLD(X4Ks3YBJ$?7&XrUi> zEH%mq|M=#kB!Qi|=+Q#eOch1g`yvC*9SwUe0&Xut{7 zOjj^xLmTLL3_K&=;WN7qp>%Uzf|V-K0!@Ozptw zUrU^3Zm3<>-g)(HV~`uTiQaS*Tj)arGH4t~>xpe^OIn;y+@XG6GqsDTAC-CgW!t}c zorh>IsoEv&q?VY8jkXrYYG@p{e`PZ3g=|)QOTNF7xLC*Hz=Li;pCxU}l0QuH!aA=F z^4mYexOqxEM$TQ-wts-Ut?KOU#p@crvVdOvP8(m2SyYLoN}Q}jX^GsrQh2+|ovwuZ zgpJJ`aWrA4rDJcH&3#c2f4$_QF zC^o}LuCckTmXO+Nv8hclk5c`nU!-!I^eR(9bohZA-5n?g{nk;goTW7jWLVu$_DgA# zXD~rTLa`YCKaSL*K0}Gt=k!Hm&L|o)DDzaww94(C7%}t54Eo^LG2R18`~wrD#uWc@ zcxa6jlLPH2aT?gM4hGb5gkUgg1YrnMm^fZbSohq4gL*JI7!-_MH4_H{=&bLacr6TM zr_tG5p^XlsuoDNg+^egr>d4h`R&r3NjomPHZZ$fhdn?Vi8yzT^olcw@H=@*tHkIy3 zEu5F!edrU$ToK()c&cKhc}^2jRr4GgomleQ{QRx8n^mPcE4l1Iy|BFzimIBskj$*mR+IiJT=21V@A>P^vTryx-} zoneuQ4g(X5XYs71X58+j8RH4a1yn%eC}Wj3!?>zgQ?+;pbB=8KX;^d0yQ|L|bNZ_B z9H<2yFt6_(AMxAazBOgkFu)MtiIPGL@Q7`O)j(tsJUa0b&j10yq~ zhE&^gqRI&X;zJ;!a1)?O={N4;$m~lhDi~K)`5Kg8>Oxt^4Tz)sc~l+!+LIF~p+g%VW8(=$YX1$4Qyc!oWyQI-%+y(;GYE21Os10d&sFUx2&!Y$uqWS*1wRILKY#Z zQeubQjsp{l~;@=97XjhXze2q@!?A z>p)7dmIBw(e}U^|ADrBigCcTXQp9K_tg*DDML$rhEy2ih{U!EM<~b+q7qvldyN{E_ zOjyy2!V$SUn4?)B=)fAvNx4}RuE@hV^zNZ&$Bj#rR@Ok{I~dgwHXwkr{VK*W!6Aip zN>2TX((2cgTA#oso(50hDxQd00RcBwpGlpJ6;i7% z!|nZANx=A_caf||C2;BM9GR@{=)2F4`QsBAb@gJa3)dmKgv5A+$zs7I8b?x#b&*KG zDoezZMy80=GU!nDk1Qy4FSdgAh6pZw1KlD#+U~iZXfauDjBRd(w=3n;uD80tr-UO) zTghuoaXV8d==H*mP@Y7Z>vemrupTS*l$!W(xxkh$u%#7sWeiUT6dv|e2F)$m?Z!${ z{pG`ASB>bk!+1h>!MV=eY(%iSBDGNpugY$PH{r3{$~wclRZ?E%HbS#?d#OcD0M>`S zHGy;d97q-3oIj(c84I`Sab*8w4ZY}&N0&h~8d6C89ORy$#x+jBywZ_@6N8kem*LjT z8=f)ETKv<&VT+a&Z+-*`zJ=ZgeeJqxVuqrWRyo39@u@T%hNH8Gla$zDnEcY zcdk%~yEppHD@yAkc~;> z9M94%6!tyiUF}`HZYVY4#&d`+7(;`Kgz79l9?vI*-$QOtj29Bb6sTNPoM60@^lIo> zy6d~MN4!ZQ`rY!rJz#z!sgzQxm06zHzFHX|0N@(Aqa{BGz=k8Yu^K z3pM}Dv6LdwcF&KQ=TltWk5eTGQ8}Gz6Zl^_yNA|GGklJ7(C>#5oF9N=V(b*xyr&P% zH{r@|!$^&dE?F|29|LQhQgFAp+vB09_S;k)^|F!OuCe&%wOCLJ7K>k zFZ~PW&NgoMg`e#E#zRyVSoS;#!w;!j>tY>%MybV=th454Nf`D>r>Y~D z9s!KFD@U+QA&esR_5?97#*(Qu3pz29biXA5bZSvQNq$Q@k9ZAxRJlKjg|b~LWqv;a z$$s#`pE|;13_lXcME-1+AZUrMhAk{D6f)!txlUC9#nkN3t?Q&Y2ANtwp6>WeGP_`^ zV~}6slnU)A);f#qH}OO-gJ{Z4n^r*?3+Wld!{b0>(Y2%dX6Vb*U%F?^L)&@!!)UQQ z(t573``C|ha1*Yh2_x6Nf+zZS5Xd-q4%&tAPY3*a3vbBlJL`~4I&^SC5-Zas0~_%M zn@|Tb3K+DNlh+z5mT-|qT*VXwAkjFr1Z_x|4<4rfpKH2s0pPsQS-fWq43v1xBW0?$ z(|;o_FopRqtGI&=sANHU{~p=}U}X_HZ8SPz2izQ%ZE5notbSp?o)L)m07n>)cGuOp z$zR3?!=BnAzTFG=JUQ27OB?Lf-l zcIH6P#HaZXED>6K=?Y8q;CO&z>o6{fd7us` z5zL?`?q=3@oX;Q3Cob9;NnWv+YC%Md5@1cR(Bm*mGsKrfh&WVp1i%;qs+bDh$n!|6 z?mmTgq@lg0JJRJo)<^VfzIx3V1F9WQM zv-uH(Pzf4*5qR!6g&f)_KN@eZ|2_hD*_nMEXI2(9aK z??8l94&#(NMdVORZ+=jY5we6>0%jCwuBVbB6u}fv0$^e4ymnXHe&f3Kt_Dy5alYdw zMdd9N6L{?OPhy+q9c!2#97~R6K1(tU7=pU(3s46LYx0Vr=?ZIsu>q(R1Vu-oLA1|; zk}9A$@;$A@R44DOZ(@(s-$bz;GXIQwE3cxMng5g8CzyWOLQ84{70cVVk&@Pb9{WGG z{?ClXisnc~0kSJ671;YYv;X5nFTte5iG6EUNpC>~_pAjdQhH*o!lc&W|FEu&?j2#}sYY=r)bk)1S@?R2PN!{o=t8 ztWsINgWDHKhWs52ks7yzyu^ePs9ubMAW)eZKVAMIs+4z@9#;&1bmRUT_0fwURBjex zlmzOO9vVVYn!mD=AEZ!5Ge{_JL6#JxU;ean!TwHj1;d8L#8z)xow?yk_YH?XX%+y(%M#J1wS*)#~<6(8_8guM*TpBQ?Tas<%_4eKdF_zl`}lLpdVw;3=2!uSyTCZvsiy53G+iCV_T=8-obc zc%2_99k171Pe$zY*vHVNa|5UySC-u|(Cixp!__>dK4okDR4K*wOXqR}3ijVq8^d+=+ zW^3xu^M>Lh6IaW$7XXjA=mPj7Uk&s=F1ZkkMjAG#3>#)Oo$Ll-`^D>8|MA2^`7+9( z^?8ZKH#u-g%Pz8LYqmW`smPPNuY2AK{w~1b3EC@TOC4Q6vKFs&>*{^52~4?+U!#V+ zkQK`ix0IbMvyTLE6`(Y7jL(z5NkRt6@E;?-sfpN1#mW3Cb^Ysm`$K2Wfs?6Tzd#RV zbPKH%@DXN`?_$6U+;}P}Eyuf?GH^l}T5m;HwUclJT^v4Y@9(3JP@x4l+}Ke@C}HL8 z`}*xS1#nvb0+0c48o36$dWI25SbI~R0iJ{1SNO_N7jq6=e!}ZBvH4|v`^fg7 zeN*7F5ttwwi%7#2#2gqIwR^%HO4nI9e-8 z#CWYGHP%~LZ8=MQbiLc(yRIP+a>CMLbIZeAzoo+==fx$_%2n;HNvblnuB=4HN+FIa zGb_K()P0Z#|BFBQU1mR(fVnK(Lf^nIAG(_g3Z$j02&H`~ z9=L;`cZr{#WC6IFa*q?;W!Y>nai0;)JK)9oX03V?z;+E#H|w@BNd@DGJ^b9GcariB zhJB5EOJ%KrW5*VoVK`cFqFx72Mp<7r426fs^$6FYMH#RbK*2_pOc?Pe1r$Dk1J@IZM>W(@LhyJ4l1 z96hc6rPzRO%`4sd3~mtMJE?GHn``(0JT^Z?CM(#)V zYhzpQ$Uro9@Ov5RSm2|>>QM4@Dkb?vybeSPLamEm zmDPC79I5zF7BRQsr}u7W(A(+Zeh{ct1+Dl=ehJ|%Tp+GyKdn(0#;JoCUaPT@#hh{+ z-zE8D5~B6g=8uOW6^>HBZt@-e_9v8*XP-_-_>BQ>zgOEqr%~^=gg+_4T)5xEFA%22 zZECHZ2m-HwoI*)Fl|K5yy-Yx$hB<7P$ literal 0 HcmV?d00001 diff --git a/stress/models/sm2vec.py b/stress/models/sm2vec.py new file mode 100644 index 0000000..ac31550 --- /dev/null +++ b/stress/models/sm2vec.py @@ -0,0 +1,413 @@ +import math +import os +import shutil +from collections import ChainMap, deque + +import numpy as np +import pandas as pd +from fastdtw import fastdtw +from gensim.models import Word2Vec +from joblib import Parallel, delayed +from tqdm import tqdm + +from ..alias import create_alias_table +from ..utils import partition_dict, preprocess_nxgraph +from ..walker import BiasedWalker +from sklearn.manifold import * +from sklearn.ensemble import * +from sklearn.cluster import * +class SM2Vec(): + def __init__(self, graph, walk_length=10, num_walks=100, workers=1, verbose=0, stay_prob=0.3, opt1_reduce_len=True, opt2_reduce_sim_calc=False, opt3_num_layers=None, temp_path='./temp/', reuse=False): + self.graph = graph + self.idx2node, self.node2idx = preprocess_nxgraph(graph) + self.idx = list(range(len(self.idx2node))) + + self.opt1_reduce_len = opt1_reduce_len + self.opt2_reduce_sim_calc = opt2_reduce_sim_calc + self.opt3_num_layers = opt3_num_layers + + self.resue = reuse + self.temp_path = temp_path + + if not os.path.exists(self.temp_path): + os.mkdir(self.temp_path) + if not reuse: + shutil.rmtree(self.temp_path) + os.mkdir(self.temp_path) + + self.pair_distances=self.create_context_graph(self.opt3_num_layers, workers, verbose) + + + def create_context_graph(self, max_num_layers, workers=1, verbose=0,): + + pair_distances = self._compute_structural_distance( + max_num_layers, workers, verbose,) + return pair_distances + def dis_matrix(self,): + return self.pair_distances + def prepare_biased_walk(self,): + + sum_weights = {} + sum_edges = {} + average_weight = {} + gamma = {} + layer = 0 + while (os.path.exists(self.temp_path+'norm_weights_distance-layer-' + str(layer)+'.pkl')): + probs = pd.read_pickle( + self.temp_path+'norm_weights_distance-layer-' + str(layer)+'.pkl') + for v, list_weights in probs.items(): + sum_weights.setdefault(layer, 0) + sum_edges.setdefault(layer, 0) + sum_weights[layer] += sum(list_weights) + sum_edges[layer] += len(list_weights) + + average_weight[layer] = sum_weights[layer] / sum_edges[layer] + + gamma.setdefault(layer, {}) + + for v, list_weights in probs.items(): + num_neighbours = 0 + for w in list_weights: + if (w > average_weight[layer]): + num_neighbours += 1 + gamma[layer][v] = num_neighbours + + layer += 1 + + pd.to_pickle(average_weight, self.temp_path + 'average_weight') + pd.to_pickle(gamma, self.temp_path + 'gamma.pkl') + + def train(self, embed_size=128, window_size=5, workers=3, iter=5): + + # pd.read_pickle(self.temp_path+'walks.pkl') + sentences = self.sentences + + print("Learning representation...") + model = Word2Vec(sentences, size=embed_size, window=window_size, min_count=0, hs=1, sg=1, workers=workers, + iter=iter) + print("Learning representation done!") + self.w2v_model = model + + return model + + def get_embeddings(self,alpha,max_layer,dim=2): + dis=np.zeros((len(list(self.graph.nodes)), len(list(self.graph.nodes)))) + layers_distances=self.pair_distances + for d1 in self.idx: + for d2 in self.idx: + if(d1==d2): + dis[int(d1)][int(d2)]=0 + else: + if((int(d1),int(d2))in layers_distances): + dis[int(d1)][int(d2)]=layers_distances[(int(d1),int(d2))][max_layer]**alpha + else: + dis[int(d1)][int(d2)]=layers_distances[(int(d2),int(d1))][max_layer]**alpha + + tmp=MDS(n_components=dim,dissimilarity='precomputed',random_state=0).fit_transform(dis) + embeddings={} + for i in range(len(tmp)): + embeddings[self.idx2node[i]]=tmp[i] + return embeddings + + def _compute_ordered_degreelist(self, max_num_layers): + + degreeList = {} + vertices = self.idx # self.g.nodes() + for v in vertices: + degreeList[v] = self._get_order_degreelist_node(v, max_num_layers) + return degreeList + + def _get_order_degreelist_node(self, root, max_num_layers=None): + if max_num_layers is None: + max_num_layers = float('inf') + + ordered_degree_sequence_dict = {} + visited = [False] * len(self.graph.nodes()) + queue = deque() + level = 0 + queue.append(root) + visited[root] = True + + while (len(queue) > 0 and level <= max_num_layers): + + count = len(queue) + if self.opt1_reduce_len: + degree_list = {} + else: + degree_list = [] + while (count > 0): + + top = queue.popleft() + node = self.idx2node[top] + degree = len(self.graph[node]) + + if self.opt1_reduce_len: + degree_list[degree] = degree_list.get(degree, 0) + 1 + else: + degree_list.append(degree) + + for nei in self.graph[node]: + nei_idx = self.node2idx[nei] + if not visited[nei_idx]: + visited[nei_idx] = True + queue.append(nei_idx) + count -= 1 + if self.opt1_reduce_len: + orderd_degree_list = [(degree, freq) + for degree, freq in degree_list.items()] + orderd_degree_list.sort(key=lambda x: x[0]) + else: + orderd_degree_list = sorted(degree_list) + ordered_degree_sequence_dict[level] = orderd_degree_list + level += 1 + + return ordered_degree_sequence_dict + + def _compute_structural_distance(self, max_num_layers, workers=1, verbose=0,): + + if os.path.exists(self.temp_path+'structural_dist.pkl'): + structural_dist = pd.read_pickle( + self.temp_path+'structural_dist.pkl') + else: + if self.opt1_reduce_len: + dist_func = cost_max + else: + dist_func = cost + + if os.path.exists(self.temp_path + 'degreelist.pkl'): + degreeList = pd.read_pickle(self.temp_path + 'degreelist.pkl') + else: + degreeList = self._compute_ordered_degreelist(max_num_layers) + pd.to_pickle(degreeList, self.temp_path + 'degreelist.pkl') + + if self.opt2_reduce_sim_calc: + degrees = self._create_vectors() + degreeListsSelected = {} + vertices = {} + n_nodes = len(self.idx) + for v in self.idx: # c:list of vertex + nbs = get_vertices( + v, len(self.graph[self.idx2node[v]]), degrees, n_nodes) + vertices[v] = nbs # store nbs + degreeListsSelected[v] = degreeList[v] # store dist + for n in nbs: + # store dist of nbs + degreeListsSelected[n] = degreeList[n] + else: + vertices = {} + for v in degreeList: + vertices[v] = [vd for vd in degreeList.keys() if vd > v] + + results = Parallel(n_jobs=workers, verbose=verbose,)( + delayed(compute_dtw_dist)(part_list, degreeList, dist_func) for part_list in partition_dict(vertices, workers)) + dtw_dist = dict(ChainMap(*results)) + + structural_dist = convert_dtw_struc_dist(dtw_dist) + pd.to_pickle(structural_dist, self.temp_path + + 'structural_dist.pkl') + + return structural_dist + + def _create_vectors(self): + degrees = {} # sotre v list of degree + degrees_sorted = set() # store degree + G = self.graph + for v in self.idx: + degree = len(G[self.idx2node[v]]) + degrees_sorted.add(degree) + if (degree not in degrees): + degrees[degree] = {} + degrees[degree]['vertices'] = [] + degrees[degree]['vertices'].append(v) + degrees_sorted = np.array(list(degrees_sorted), dtype='int') + degrees_sorted = np.sort(degrees_sorted) + + l = len(degrees_sorted) + for index, degree in enumerate(degrees_sorted): + if (index > 0): + degrees[degree]['before'] = degrees_sorted[index - 1] + if (index < (l - 1)): + degrees[degree]['after'] = degrees_sorted[index + 1] + + return degrees + + def _get_layer_rep(self, pair_distances): + layer_distances = {} + layer_adj = {} + for v_pair, layer_dist in pair_distances.items(): + for layer, distance in layer_dist.items(): + vx = v_pair[0] + vy = v_pair[1] + + layer_distances.setdefault(layer, {}) + layer_distances[layer][vx, vy] = distance + + layer_adj.setdefault(layer, {}) + layer_adj[layer].setdefault(vx, []) + layer_adj[layer].setdefault(vy, []) + layer_adj[layer][vx].append(vy) + layer_adj[layer][vy].append(vx) + + return layer_adj, layer_distances + + def _get_transition_probs(self, layers_adj, layers_distances): + layers_alias = {} + layers_accept = {} + + for layer in layers_adj: + + neighbors = layers_adj[layer] + layer_distances = layers_distances[layer] + node_alias_dict = {} + node_accept_dict = {} + norm_weights = {} + + for v, neighbors in neighbors.items(): + e_list = [] + sum_w = 0.0 + + for n in neighbors: + if (v, n) in layer_distances: + wd = layer_distances[v, n] + else: + wd = layer_distances[n, v] + w = np.exp(-float(wd)) + e_list.append(w) + sum_w += w + + e_list = [x / sum_w for x in e_list] + norm_weights[v] = e_list + accept, alias = create_alias_table(e_list) + node_alias_dict[v] = alias + node_accept_dict[v] = accept + + pd.to_pickle( + norm_weights, self.temp_path + 'norm_weights_distance-layer-' + str(layer)+'.pkl') + + layers_alias[layer] = node_alias_dict + layers_accept[layer] = node_accept_dict + + return layers_accept, layers_alias + + +def cost(a, b): + ep = 0.5 + m = max(a, b) + ep + mi = min(a, b) + ep + return ((m / mi) - 1) + + +def cost_min(a, b): + ep = 0.5 + m = max(a[0], b[0]) + ep + mi = min(a[0], b[0]) + ep + return ((m / mi) - 1) * min(a[1], b[1]) + + +def cost_max(a, b): + ep = 0.5 + m = max(a[0], b[0]) + ep + mi = min(a[0], b[0]) + ep + return ((m / mi) - 1) * max(a[1], b[1]) + + +def convert_dtw_struc_dist(distances, startLayer=1): + """ + + :param distances: dict of dict + :param startLayer: + :return: + """ + for vertices, layers in distances.items(): + keys_layers = sorted(layers.keys()) + startLayer = min(len(keys_layers), startLayer) + for layer in range(0, startLayer): + keys_layers.pop(0) + + for layer in keys_layers: + layers[layer] += layers[layer - 1] + return distances + + +def get_vertices(v, degree_v, degrees, n_nodes): + a_vertices_selected = 2 * math.log(n_nodes, 2) + vertices = [] + try: + c_v = 0 + + for v2 in degrees[degree_v]['vertices']: + if (v != v2): + vertices.append(v2) # same degree + c_v += 1 + if (c_v > a_vertices_selected): + raise StopIteration + + if ('before' not in degrees[degree_v]): + degree_b = -1 + else: + degree_b = degrees[degree_v]['before'] + if ('after' not in degrees[degree_v]): + degree_a = -1 + else: + degree_a = degrees[degree_v]['after'] + if (degree_b == -1 and degree_a == -1): + raise StopIteration # not anymore v + degree_now = verifyDegrees(degrees, degree_v, degree_a, degree_b) + # nearest valid degree + while True: + for v2 in degrees[degree_now]['vertices']: + if (v != v2): + vertices.append(v2) + c_v += 1 + if (c_v > a_vertices_selected): + raise StopIteration + + if (degree_now == degree_b): + if ('before' not in degrees[degree_b]): + degree_b = -1 + else: + degree_b = degrees[degree_b]['before'] + else: + if ('after' not in degrees[degree_a]): + degree_a = -1 + else: + degree_a = degrees[degree_a]['after'] + + if (degree_b == -1 and degree_a == -1): + raise StopIteration + + degree_now = verifyDegrees(degrees, degree_v, degree_a, degree_b) + + except StopIteration: + return list(vertices) + + return list(vertices) + + +def verifyDegrees(degrees, degree_v_root, degree_a, degree_b): + + if(degree_b == -1): + degree_now = degree_a + elif(degree_a == -1): + degree_now = degree_b + elif(abs(degree_b - degree_v_root) < abs(degree_a - degree_v_root)): + degree_now = degree_b + else: + degree_now = degree_a + + return degree_now + + +def compute_dtw_dist(part_list, degreeList, dist_func): + dtw_dist = {} + for v1, nbs in part_list: + lists_v1 = degreeList[v1] # lists_v1 :orderd degree list of v1 + for v2 in nbs: + lists_v2 = degreeList[v2] # lists_v1 :orderd degree list of v2 + max_layer = min(len(lists_v1), len(lists_v2)) # valid layer + dtw_dist[v1, v2] = {} + for layer in range(0, max_layer): + dist, path = fastdtw( + lists_v1[layer], lists_v2[layer], radius=1, dist=dist_func) + dtw_dist[v1, v2][layer] = dist + return dtw_dist diff --git a/stress/utils.py b/stress/utils.py new file mode 100644 index 0000000..8929eec --- /dev/null +++ b/stress/utils.py @@ -0,0 +1,48 @@ +def preprocess_nxgraph(graph): + node2idx = {} + idx2node = [] + node_size = 0 + for node in graph.nodes(): + node2idx[node] = node_size + idx2node.append(node) + node_size += 1 + return idx2node, node2idx + + +def partition_dict(vertices, workers): + batch_size = (len(vertices) - 1) // workers + 1 + part_list = [] + part = [] + count = 0 + for v1, nbs in vertices.items(): + part.append((v1, nbs)) + count += 1 + if count % batch_size == 0: + part_list.append(part) + part = [] + if len(part) > 0: + part_list.append(part) + return part_list + + +def partition_list(vertices, workers): + batch_size = (len(vertices) - 1) // workers + 1 + part_list = [] + part = [] + count = 0 + for v1, nbs in enumerate(vertices): + part.append((v1, nbs)) + count += 1 + if count % batch_size == 0: + part_list.append(part) + part = [] + if len(part) > 0: + part_list.append(part) + return part_list + + +def partition_num(num, workers): + if num % workers == 0: + return [num//workers]*workers + else: + return [num//workers]*workers + [num % workers] diff --git a/stress/walker.py b/stress/walker.py new file mode 100644 index 0000000..7266585 --- /dev/null +++ b/stress/walker.py @@ -0,0 +1,276 @@ +import itertools +import math +import random + +import numpy as np +import pandas as pd +from joblib import Parallel, delayed +from tqdm import trange + +from .alias import alias_sample, create_alias_table +from .utils import partition_num + + +class RandomWalker: + def __init__(self, G, p=1, q=1, use_rejection_sampling=0): + """ + :param G: + :param p: Return parameter,controls the likelihood of immediately revisiting a node in the walk. + :param q: In-out parameter,allows the search to differentiate between “inward” and “outward” nodes + :param use_rejection_sampling: Whether to use the rejection sampling strategy in node2vec. + """ + self.G = G + self.p = p + self.q = q + self.use_rejection_sampling = use_rejection_sampling + + def deepwalk_walk(self, walk_length, start_node): + + walk = [start_node] + + while len(walk) < walk_length: + cur = walk[-1] + cur_nbrs = list(self.G.neighbors(cur)) + if len(cur_nbrs) > 0: + walk.append(random.choice(cur_nbrs)) + else: + break + return walk + + def node2vec_walk(self, walk_length, start_node): + + G = self.G + alias_nodes = self.alias_nodes + alias_edges = self.alias_edges + + walk = [start_node] + + while len(walk) < walk_length: + cur = walk[-1] + cur_nbrs = list(G.neighbors(cur)) + if len(cur_nbrs) > 0: + if len(walk) == 1: + walk.append( + cur_nbrs[alias_sample(alias_nodes[cur][0], alias_nodes[cur][1])]) + else: + prev = walk[-2] + edge = (prev, cur) + next_node = cur_nbrs[alias_sample(alias_edges[edge][0], + alias_edges[edge][1])] + walk.append(next_node) + else: + break + + return walk + + def node2vec_walk2(self, walk_length, start_node): + """ + Reference: + KnightKing: A Fast Distributed Graph Random Walk Engine + http://madsys.cs.tsinghua.edu.cn/publications/SOSP19-yang.pdf + """ + + def rejection_sample(inv_p, inv_q, nbrs_num): + upper_bound = max(1.0, max(inv_p, inv_q)) + lower_bound = min(1.0, min(inv_p, inv_q)) + shatter = 0 + second_upper_bound = max(1.0, inv_q) + if (inv_p > second_upper_bound): + shatter = second_upper_bound / nbrs_num + upper_bound = second_upper_bound + shatter + return upper_bound, lower_bound, shatter + + G = self.G + alias_nodes = self.alias_nodes + inv_p = 1.0 / self.p + inv_q = 1.0 / self.q + walk = [start_node] + while len(walk) < walk_length: + cur = walk[-1] + cur_nbrs = list(G.neighbors(cur)) + if len(cur_nbrs) > 0: + if len(walk) == 1: + walk.append( + cur_nbrs[alias_sample(alias_nodes[cur][0], alias_nodes[cur][1])]) + else: + upper_bound, lower_bound, shatter = rejection_sample( + inv_p, inv_q, len(cur_nbrs)) + prev = walk[-2] + prev_nbrs = set(G.neighbors(prev)) + while True: + prob = random.random() * upper_bound + if (prob + shatter >= upper_bound): + next_node = prev + break + next_node = cur_nbrs[alias_sample( + alias_nodes[cur][0], alias_nodes[cur][1])] + if (prob < lower_bound): + break + if (prob < inv_p and next_node == prev): + break + _prob = 1.0 if next_node in prev_nbrs else inv_q + if (prob < _prob): + break + walk.append(next_node) + else: + break + return walk + + def simulate_walks(self, num_walks, walk_length, workers=1, verbose=0): + + G = self.G + + nodes = list(G.nodes()) + + results = Parallel(n_jobs=workers, verbose=verbose, )( + delayed(self._simulate_walks)(nodes, num, walk_length) for num in + partition_num(num_walks, workers)) + + walks = list(itertools.chain(*results)) + + return walks + + def _simulate_walks(self, nodes, num_walks, walk_length,): + walks = [] + for _ in range(num_walks): + random.shuffle(nodes) + for v in nodes: + if self.p == 1 and self.q == 1: + walks.append(self.deepwalk_walk( + walk_length=walk_length, start_node=v)) + elif self.use_rejection_sampling: + walks.append(self.node2vec_walk2( + walk_length=walk_length, start_node=v)) + else: + walks.append(self.node2vec_walk( + walk_length=walk_length, start_node=v)) + return walks + + def get_alias_edge(self, t, v): + """ + compute unnormalized transition probability between nodes v and its neighbors give the previous visited node t. + :param t: + :param v: + :return: + """ + G = self.G + p = self.p + q = self.q + + unnormalized_probs = [] + for x in G.neighbors(v): + weight = G[v][x].get('weight', 1.0) # w_vx + if x == t: # d_tx == 0 + unnormalized_probs.append(weight/p) + elif G.has_edge(x, t): # d_tx == 1 + unnormalized_probs.append(weight) + else: # d_tx > 1 + unnormalized_probs.append(weight/q) + norm_const = sum(unnormalized_probs) + normalized_probs = [ + float(u_prob)/norm_const for u_prob in unnormalized_probs] + + return create_alias_table(normalized_probs) + + def preprocess_transition_probs(self): + """ + Preprocessing of transition probabilities for guiding the random walks. + """ + G = self.G + alias_nodes = {} + for node in G.nodes(): + unnormalized_probs = [G[node][nbr].get('weight', 1.0) + for nbr in G.neighbors(node)] + norm_const = sum(unnormalized_probs) + normalized_probs = [ + float(u_prob)/norm_const for u_prob in unnormalized_probs] + alias_nodes[node] = create_alias_table(normalized_probs) + + if not self.use_rejection_sampling: + alias_edges = {} + + for edge in G.edges(): + alias_edges[edge] = self.get_alias_edge(edge[0], edge[1]) + if not G.is_directed(): + alias_edges[(edge[1], edge[0])] = self.get_alias_edge(edge[1], edge[0]) + self.alias_edges = alias_edges + + self.alias_nodes = alias_nodes + return + + +class BiasedWalker: + def __init__(self, idx2node, temp_path): + + self.idx2node = idx2node + self.idx = list(range(len(self.idx2node))) + self.temp_path = temp_path + pass + + def simulate_walks(self, num_walks, walk_length, stay_prob=0.3, workers=1, verbose=0): + + layers_adj = pd.read_pickle(self.temp_path+'layers_adj.pkl') + layers_alias = pd.read_pickle(self.temp_path+'layers_alias.pkl') + layers_accept = pd.read_pickle(self.temp_path+'layers_accept.pkl') + gamma = pd.read_pickle(self.temp_path+'gamma.pkl') + walks = [] + initialLayer = 0 + + nodes = self.idx # list(self.g.nodes()) + + results = Parallel(n_jobs=workers, verbose=verbose, )( + delayed(self._simulate_walks)(nodes, num, walk_length, stay_prob, layers_adj, layers_accept, layers_alias, gamma) for num in + partition_num(num_walks, workers)) + + walks = list(itertools.chain(*results)) + return walks + + def _simulate_walks(self, nodes, num_walks, walk_length, stay_prob, layers_adj, layers_accept, layers_alias, gamma): + walks = [] + for _ in range(num_walks): + random.shuffle(nodes) + for v in nodes: + walks.append(self._exec_random_walk(layers_adj, layers_accept, layers_alias, + v, walk_length, gamma, stay_prob)) + return walks + + def _exec_random_walk(self, graphs, layers_accept, layers_alias, v, walk_length, gamma, stay_prob=0.3): + initialLayer = 0 + layer = initialLayer + + path = [] + path.append(self.idx2node[v]) + + while len(path) < walk_length: + r = random.random() + if(r < stay_prob): # same layer + v = chooseNeighbor(v, graphs, layers_alias, + layers_accept, layer) + path.append(self.idx2node[v]) + else: # different layer + r = random.random() + try: + x = math.log(gamma[layer][v] + math.e) + p_moveup = (x / (x + 1)) + except: + print(layer, v) + raise ValueError() + + if(r > p_moveup): + if(layer > initialLayer): + layer = layer - 1 + else: + if((layer + 1) in graphs and v in graphs[layer + 1]): + layer = layer + 1 + + return path + + +def chooseNeighbor(v, graphs, layers_alias, layers_accept, layer): + + v_list = graphs[layer][v] + + idx = alias_sample(layers_accept[layer][v], layers_alias[layer][v]) + v = v_list[idx] + + return v diff --git a/usa2.out b/usa2.out new file mode 100644 index 0000000..5923445 --- /dev/null +++ b/usa2.out @@ -0,0 +1 @@ +10 cross val: 0.6515824510490053 0.6571428571428571 diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..cbf274c --- /dev/null +++ b/utils/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat Apr 29 17:50:00 2017 + + +""" + diff --git a/utils/__init__.pyc b/utils/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..78a8c66cab6e7464834cc9ceea84dfe487a8911d GIT binary patch literal 169 zcmZSn%*%C=TOvN00SXv_v;zlgegw!7; literal 0 HcmV?d00001 diff --git a/utils/__pycache__/__init__.cpython-36.pyc b/utils/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..353d81ecf88204527e941c0f4a62ea9609d0221f GIT binary patch literal 172 zcmXr!<>gv4i8aBUfq~&M5W@i@kmUfx#T-B)g&~R|g)x{xlc`Fb%eg2uu_QG`AwN$c zII%>*v7ku7$Wp=3+{)Cz%D_Ou$iUE?i;K%olkpaNe0)lNa(w(sh9V}QDPZE4ntn!p zZmNDxW=^KQv%iaLys@#VnSNhDNPTEM@@0H{?C)Id#j&y6AHTTYO^y)q zCplJZ7~g=JGH4hn6GoX8(XwTFyKI}@DLbZj%dY7&e#%eYjXA?lrGi#FsQ=O^Yjj*j6LN5DNCgM0$xtDM{SzoO>*h6ul zjzV35nnuuc0m!Z=zf`1ab?FRY7F7Gl`svi6qv(#+C0*?8Bb$#H57knBdEUs+a zyj59TymYzPR?R5wwT0wBduh1GE3h51q&aAa<dGHlMqSns-5eRBs1{WlZ1LSPp7PLDo?^(l|q9BB^o-wdH6ZVqYOv%kUk{w ztV0yt&B;$G!LLgW>9-`d9)Y}IKDr)Q+O5G^O6R@_qc*=KrI0Y`D88?BMsl?mMsI_2 zLM3V+!BKr+762QkIVxviZU_v;AJnu2KZ@*tl9~04JSR5+AVP#W@KP9AKad(_Hc-8; zg;ap&gbqlV^ZO-?nyD(JLaO;)esB$CBaXR&zvEOL7!q^v*aXI8{D3vT1 zi!o>0p{h1`1jGVZptv20dU2stx^i)$Xc#NFPcyC;8mbiy`R6w|_qT*lje~P=NGpkW zi^nQdO%dans=C)1b;Z{SXqO~(nH=(9JGl{q^Ss~rhN~@ z$dG5CS%BJy05Vu{qTNu+@IYrnSw{;(n4y1asGm<&Q%Ta6{B9$xfpq zpF?Il=BkrPBB9daFyCSjW6nj-PJe|)fj1vv^04H4iYjZz#^5`mKSG*dcHOE|9WMvu!+t2h~n1-#=2Ry@nGx!k!ZnaG6nFE5}Gj{iwS|VI%qtM*=tz_=&C}(^_Ga3 z;bLPH15tvZNZGo>v}-i+M)aW9ndreRYocfJkaqj=Q@7q3K~0FDOi!`B_!@@M3T)I1 zBicEG4zkYG0(izh1#%}>G3F=$z2lxu{j(|TYu8$86?%t-D%6=x(Uw(S&TK&#a`iX# zCTX1>pr1zcjLeyR}Abm(_lUDv>m|%#+6}Q=a66a^+eomZF5->wVoQ}$8fIB;vt|A?V5wN zn}E})Agk$`{2cM)T`%z+QXV%}u3%!UNS?^cIO!qVU6>lAC&OgY)95jKT!OVGXOcW# zv{Ue+nT0EN7Cw*4C7=crtgsr4>1?IKM72`UE&xsr3{3L|F|QB#KCIPVUn%=?5q{0P r$UG^`^=(q0+4GpT&Ev$t@~*Z7Ye)P#=5m9{ffrW)vvW{9&&&S>^4+50 literal 0 HcmV?d00001 diff --git a/utils/function_utils.py b/utils/function_utils.py new file mode 100644 index 0000000..82b8ba0 --- /dev/null +++ b/utils/function_utils.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +""" +Useful functions for investigating the distribution of the diffusion coefficients +""" +import copy +from graph_tools import * +import numpy as np +import pandas as pd +import seaborn as sb + + +def h(x, epsilon=10**(-6)): + if x > epsilon: + return - (x) * np.log(x) + elif x < 0: + print "error: argument is negative" + return np.nan + else: + return -(x + epsilon) * np.log(x + epsilon) + + +def entropy(mat, nb_bins=20): + N, m = mat.shape + ent = np.zeros(m) + for i in range(m): + h, w = np.histogram(mat[:, i], bins=nb_bins) + v=[(0.5 * (w[k+1] - w[k]) + w[k]) for k in range(nb_bins)] + ent[i] = 1.0 / N * np.sum([-h[k] * np.log(v[k]) + for k in range(nb_bins)]) + return ent + + +def variance_without_diagonal(mat, recompute_mean=False): + var = np.zeros(mat.shape[1]) + mu = np.zeros(mat.shape[1]) + N = mat.shape[0] + for i in range(mat.shape[1]): + if recompute_mean: + mu[i] = 1.0 / (N-1) * (N * np.mean(mat[:, i]) - mat[i, i]) + else: + mu[i] = 1.0 / N + var[i] = np.mean([(mat[j, i] - mu[i])**2 + for j in range(mat.shape[0]) if j != i]) + return var, mu + + +def entropy_naive(mat, centered=False, offset=False, norm=False): + ent = np.zeros(mat.shape[1]) + N = mat.shape[1] + if centered and offset: + centered = False + if centered: + mat2 = np.abs(mat - 1.0 / N * np.ones((mat.shape[0], mat.shape[1]))) + elif offset: + mat2 = copy.deepcopy(mat) + np.fill_diagonal(mat2, 0) + else: + mat2 = copy.deepcopy(mat) + if norm: + mat2 = normalize_matrix(mat2, direction="column", type_norm="l1") + epsilon = 0.05 * 1.0 / N + for i in range(mat.shape[1]): + if offset: + ent[i] = np.mean([- mat2[j, i] * np.log(mat2[j, i]) + for j in range(mat.shape[0]) if j != i]) + else: + ent[i] = np.mean([h(mat2[j, i], epsilon) + for j in range(mat.shape[0])]) + return ent diff --git a/utils/graph_tools.py b/utils/graph_tools.py new file mode 100644 index 0000000..eaee467 --- /dev/null +++ b/utils/graph_tools.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +""" +Tools for the analysis of the Graph +""" +import matplotlib.pyplot as plt +import networkx as nx +import numpy as np +import seaborn as sb +import scipy as sc + + +def laplacian(a): + n_nodes, _ = a.shape + posinv = np.vectorize(lambda x: float(1.0)/np.sqrt(x) if x>1e-10 else 0.0) + d = sc.sparse.diags(np.array(posinv(a.sum(0))).reshape([-1,]),0) + lap = sc.sparse.eye(n_nodes) - d.dot(a.dot(d)) + return lap + + +def degree_matrix(adj): + n, _ =adj.shape + deg = np.diag([np.sum(adj[i, :]) for i in range(n)]) + return deg + + +def Invdegree_matrix(adj): + n, _ = adj.shape + pos = np.vectorize(lambda x: x if x > 0 else 1) + deg_prov = pos(np.array(adj.sum(0))) + deg = np.diag(1.0 / deg_prov) + return deg + + +def normalize_matrix(m, direction="row", type_norm="max"): + n, _ = m.shape + if direction == "row": + if type_norm == "max": + deg = [1.0 / np.max(m[i, :]) for i in range(n)] + elif type_norm == "l2": + deg=[1.0 / np.linalg.norm(m[i, :]) for i in range(n)] + elif type_norm == "l1": + deg=[1.0 / np.sum(np.abs(m[i,:])) for i in range(n)] + else: + print "direction not recognized. degefaulting to l2" + deg=[1.0 / np.linalg.norm(m[i, :]) for i in range(n)] + deg = np.diag(deg) + return deg.dot(m) + elif direction == "column": + m_tilde = normalize_matrix(m.T, direction="row", type_norm=type_norm) + return m_tilde.T + else: + print "direction not recognized. degefaulting to column" + return normalize_matrix(m.T, direction="row", type_norm=type_norm) diff --git a/utils/graph_tools.pyc b/utils/graph_tools.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a63f00eed2a4e8a480cd1095520390e519bc253 GIT binary patch literal 2593 zcmb7F&2Af26h1Q^|0ZclA&~xnOslp=R4G(!ke~q?sb!PJIO@WpSQF3K8FxJ6&b>}! zeuV+=?r(gAfObR}_Q=t`$_@aajXe85+vQ$65o(y1Tt4e2aMSdu5uvnZjb%#ws< zWzI-gkq`%K@&uZfX{Ft&)A&`8##WXkrrFQ(rrn8}K^i1e6Psq%*YCS|Fy3jz|KhjV zb0A;AQ^s=#kNFN{CNdQH!j*kT_Fb{+0Gt7uZ?IAlTauwC!?JEwWLDB60OV4j_#f8j zz(7B_4sG7S!Me&nJO^0D#Y9p(fHLMInV#4vllh*wy}AIN@1(!YhO zJXQ7MbE<9}QKj=1fL^5SYt{CHYAdU@nsXf3ts~kh3a?5JPf!Ry6ydL`bA#8--FwHC z{U2x-95~8w)MQrC*2SGsks+=D9oB6$Kdv(d^Lxh@7Xq$7Tp(D75U0Dl53p4kE}(uJ zK=UH8HbULjF}vx%jXe67K>(eeRBhgVVq<3##!1-Gus584N}bEaIJ|N ziu%DMv2i+R+N_Cl?B-sUOh&0?p&XvoFFPGan6dfDymxf(rFsj6EzYN+VOGg$FA}^O zO=8^Q1HG7NL7S+UW7|fX$zP@@tDpNp0vF~}NoU(ui^Z+%$iD{GzfN-4cm73wUZPAD zWYopw7DlJ*IsaXpAW}oZ*|&(lbv&Qpx#yO_FFQ-%FFI9xwTM#9bh}~J>vrucSilG! zCz(y+ZQP^eiYuyMbt)uQr$QRp$65YxPm`GL>4Z-wqw%zu{Dg0!U^~lGl`z{XVR|tn r7zF=yk~c}3Bt-wrQRQBK#gDRZl0>&T01f9>W$raRFV$=HO1<_U`1srj literal 0 HcmV?d00001 diff --git a/utils/utils.py b/utils/utils.py new file mode 100644 index 0000000..f3b201a --- /dev/null +++ b/utils/utils.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +### Random tools useful for saveing stuff and manipulating pickle/numpy objects +import numpy as np +import pickle +import gzip +import re +import networkx as nx + + +def save_obj(obj, name, path, compress=False): + # print path+name+ ".pkl" + if compress is False: + with open(path + name + ".pkl", 'wb') as f: + pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL) + else: + with gzip.open(path + name + '.pklz','wb') as f: + pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL) + + +def load_obj(name,compressed=False): + if compressed is False: + with open(name, 'rb') as f: + return pickle.load(f) + else: + with gzip.open(name,'rb') as f: + return pickle.load(f) + + + +def atof(text): + try: + retval = float(text) + except ValueError: + retval = text + return retval + + +def natural_keys(l): + ''' + alist.sort(key=natural_keys) sorts in human order + http://nedbatchelder.com/blog/200712/human_sorting.html + (See Toothy's implementation in the comments) + float regex comes from https://stackoverflow.com/a/12643073/190597 + ''' + t = np.array([ int(re.split(r"([a-zA-Z]*)([0-9]*)", c)[2]) for c in l ]) + order = np.argsort(t) + return [l[o] for o in order] + + +def saveNet2txt(G, colors=[], name="net", path="plots/"): + '''saves graph to txt file (for Gephi plotting) + INPUT: + ======================================================================== + G: nx graph + colors: colors of the nodes + name: name of the file + path: path of the storing folder + OUTPUT: + ======================================================================== + 2 files containing the edges and the nodes of the corresponding graph + ''' + if len(colors) == 0: + colors = range(nx.number_of_nodes(G)) + graph_list_rep = [["Id","color"]] + [[i,colors[i]] + for i in range(nx.number_of_nodes(G))] + np.savetxt(path + name + "_nodes.txt", graph_list_rep, fmt='%s %s') + edges = G.edges(data=False) + edgeList = [["Source", "Target"]] + [[v[0], v[1]] for v in edges] + np.savetxt(path + name + "_edges.txt", edgeList, fmt='%s %s') + print ("saved network edges and nodes to txt file (for Gephi vis)") + return + diff --git a/utils/utils.pyc b/utils/utils.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8785a536a77b20caae91d041a7ba470e4452fe74 GIT binary patch literal 2895 zcmcImZF3V<6h51mzND#C1WK7f7iS!|I3%Tj*p4_jfQ1<*#k2@h2IDq+lWe=$yWV?K zS|eD_!Q%|GLB(eL`4vq@ldw0_XEd-vqNob#OLo|hDVov-{dcfQr8(Wiv>Z9Mh| z3=z=|MvtNbB_8b*#&VH%ietG%JEgH)rk(Owo}!&;QZp14={3&Iid+)8LQ$DsL-`y< zQzBHU3q#WsVgD?>hW>drx)oFy%V`Xi+u^|Vv|0DtkxtXlRpQ_AX|x$}8P5!!J9q^7 zut<(*e}>FGavlu}H1uc@o-9J^s{;Lak&a8`3ba?GA<;0GOZ2Kp-V?a}_0x2XT$%RX zoGt$Qvrw=VFs_E>v6k&8Fh%rY*D_N6{xXH`-iHXm!*ksPt%foehHJa$;V1}ap&3*HBXi(Z?ZVS|iSIR6d;7#?wc zT{xG>VXn{6abe6g*!O5_L~%fX%M_ouRTyQf4I$F(iqlQ@rpePyMkBr_I*gi(E8wXn zJMS3%m;n_v=Xe#*i4?FdreG0!a|*nwciKBwIP109G+So!g@PJ{qXnh_?!d`okDjE9 zR08Gu6*9}@c^+0UoqF^XWNihkqYh}iyF!i;Gl$o6DIhU>1>#2%%L)Y%91dBD?a(y?^-TLav%FU~* zbvf8#J#pHt^;|!hoDa5?^0&2iy`zs|q@N|KkMs*&tW&n>ddi17p0mr7Q*uYXQC)S& ztIGNvqx(LCu|Q*8*xuI%%3$9MK@--mu6}y`+RDvq^{ZAq!DdP99N%PUxWA(|2Xrx3W3dwWydW5Crb@{S=(vzeG1P9bV9(D5`4(TF@+;#Xy2<7e2I`IC(~ z*npCWji^c+_oI14`a5vk{)9{5GHU&<3A3K>wC@g`--#3D2OVwv4VCp`pULC+%%ki< zf9&2rMJs0+r!GHG>0wOAkz2iMWkaR4(Qm zl+xQ0OsvGN^BiI#@{v0)wAuIH0xY)vE=&$$yW9w*p>Z8eP?$K=O_;)#REk4)3KQv| zzpG43cXH^>bC{F*z-HMGJ|%#pe+HbeQW7=q5wVBOPcW1JM&Mf320): + pts_colors[i]="color_1" + if(i==9 or i==20): + pts_colors[i]="color_2" + if(i==10 or i==19): + pts_colors[i]="color_3" + if(i==11 or i==18): + pts_colors[i]="color_4" + if(i==12 or i==17): + pts_colors[i]="color_5" + if(i==13 or i==16): + pts_colors[i]="color_6" + if(i==14 or i==15): + pts_colors[i]="color_7" + + for i in range(7): + color_paltette[i] = (color_paltette[i][0] / 255, color_paltette[i][1] / 255, color_paltette[i][2] / 255) + + + # reorganize dataset + draw_dataset = {'x': X, + 'y': Y, + 'label':list(range(1, 30 + 1)), + 'ptsize': dot_size, + "cpaltette": color_paltette, + 'colors':pts_colors} + + #draw scatterplot points + ax = sns.scatterplot(x = "x",y = "y", alpha = 1,s = draw_dataset["ptsize"],hue="colors", palette=draw_dataset["cpaltette"], legend = legend_setting, data = draw_dataset) + + + return ax +if __name__ == "__main__": + random.seed(0) + np.random.seed(0) + graph = nx.read_weighted_edgelist("data/barbell.edgelist", delimiter=" ", nodetype=None,create_using=nx.Graph()) + nx.set_edge_attributes(graph, name="weight", values={edge: 1 + for edge, weight in nx.get_edge_attributes(graph, name="weight").items()}) + + + for our_size in [2]: + + +############################################################################################ + model = SM2Vec(graph.to_directed(), walk_length=10, num_walks=80,workers=8, verbose=40 ) + embeddings=model.get_embeddings(1,6) + print(embeddings) + ax=plot(embeddings) + ax.axis("equal") + ax.figure.savefig("barbell.pdf",bbox_inches='tight') + diff --git a/vis_karate.py b/vis_karate.py new file mode 100644 index 0000000..ca1fa42 --- /dev/null +++ b/vis_karate.py @@ -0,0 +1,100 @@ +from sklearn.metrics import roc_auc_score +import numpy as np +import random +from stress.classify import read_node_label, Classifier +from stress import * +from sklearn.linear_model import LogisticRegression +from sklearn.model_selection import StratifiedShuffleSplit, StratifiedKFold +from sklearn.metrics import f1_score +from sklearn.preprocessing import StandardScaler +from sklearn.svm import SVC +import pandas as pd +import matplotlib.pyplot as plt +import networkx as nx +from sklearn.manifold import TSNE +from sklearn.linear_model import LogisticRegression +import seaborn as sns +from sklearn.manifold import MDS +def plot(embeddings): + X=[] + Y=[] + Label=[] + for i in range(1,69): + X.append(embeddings[str(i)][0]) + Y.append(embeddings[str(i)][1]) + canvas_height = 15 + canvas_width = 15 + dot_size = 1000 + text_size = 18 + legend_setting = False #“brief” / “full” / False + + + sns.set(style="whitegrid") + + # set canvas height & width + plt.figure(figsize=(canvas_width, canvas_height)) + + pts_num = 68 + # add categorical information () + pts_colors = list(range(pts_num)) + + lnum = [21,19,27,15,23,30,16,33,24,34,10,31,29,28,26,14, 3, 9,32,25, 4, 8, 2,20,13,22, 1,18, 6,11,17, 7, 5,12] + rnum = [46,61,68,64,47,36,66,51,35,42,58,65,56,45,57,60,38,41,48,44,59,43,39,54,62,49,37,40,50,53,52,55,63,67] + + + for i in range(len(lnum)): + pts_colors[lnum[i] - 1] = "color_" + str(i + 1) + pts_colors[rnum[i] - 1] = "color_" + str(i + 1) + + + # set color paltette + color_paltette_0 = [(103, 99, 222),(194, 154, 223),(64,111,87),(126,128,219),(198,103,62),(59,134,138),(177,105,42),(136,41,191),(111,236,113),(82,130,129),(67,19,62),(229,82,40),(226,72,200),(120,188,197),(134,241,185),(157,116,156),(192,137,224),(103,211,168),(86,118,192),(107,74,28),(113,128,224), (148,176,176), (62,108,119),(176,105,175),(41,96,181),(220,76,203),(152,229,115),(214,51,54),(235,79,237),(142,197,138),(63,52,240),(232,242,79),(95,202,119),(181,195,235)] + color_paltette=list(range(len(color_paltette_0))) + for i in range(len(lnum)): + j = min(lnum[i], rnum[i]) - 1 + color_paltette[j] = color_paltette_0[i] + + for i in range(len(lnum)): + color_paltette[i] = (color_paltette[i][0] / 255, color_paltette[i][1] / 255, color_paltette[i][2] / 255) + + + # reorganize dataset + draw_dataset = {'x': X, + 'y': Y, + 'label':list(range(1, pts_num + 1)), + 'ptsize': dot_size, + "cpaltette": color_paltette, + 'colors':pts_colors} + + #draw scatterplot points + ax = sns.scatterplot(x = "x",y = "y", alpha = 1,s = draw_dataset["ptsize"],hue="colors", palette=draw_dataset["cpaltette"], legend = legend_setting, data = draw_dataset) + + + + # add text on point circle + for i in range(pts_num-34): + ax.text(X[i], Y[i], i+1 ,horizontalalignment='center',verticalalignment='center', size=text_size, color='white', weight='semibold') + + + + + return ax +if __name__ == "__main__": + random.seed(0) + np.random.seed(0) + graph = nx.read_weighted_edgelist("data/karate-mirrored2.edgelist", delimiter=" ", nodetype=None,create_using=nx.Graph()) + nx.set_edge_attributes(graph, name="weight", values={edge: 1 + for edge, weight in nx.get_edge_attributes(graph, name="weight").items()}) + + + for our_size in [2]: + + +############################################################################################ + model = SM2Vec(graph.to_directed(), walk_length=10, num_walks=80,workers=8, verbose=40 ) + embeddings=model.get_embeddings(1,3) + print(embeddings) + ax=plot(embeddings) + ax.axis("equal") + ax.figure.savefig("karate.pdf",bbox_inches='tight') +