Commit 0ce8bd23 authored by Fize Jacques's avatar Fize Jacques

Add parallelization + prepare test

parent 31bf928c
...@@ -7,9 +7,11 @@ cdef class Base: ...@@ -7,9 +7,11 @@ cdef class Base:
## Methods ## Methods
cpdef np.ndarray compare(self,list graph_list, list selected) cpdef np.ndarray compare(self,list graph_list, list selected)
cpdef np.ndarray compare_old(self,list listgs, list selected)
cpdef np.ndarray distance(self, np.ndarray matrix) cpdef np.ndarray distance(self, np.ndarray matrix)
cpdef np.ndarray similarity(self, np.ndarray matrix) cpdef np.ndarray similarity(self, np.ndarray matrix)
cpdef bint isAccepted(self,G,index,selected) cpdef bint isAccepted(self,G,index,selected)
cpdef list get_selected_array(self,selected,size_corpus)
cpdef intersection(G,H) cpdef intersection(G,H)
cpdef union_(G,H) cpdef union_(G,H)
...@@ -136,6 +136,17 @@ cdef class Base: ...@@ -136,6 +136,17 @@ cdef class Base:
else: else:
self.type_alg=type_alg self.type_alg=type_alg
self.normalized=normalized self.normalized=normalized
cpdef list get_selected_array(self,selected,size_corpus):
cdef list selected_test = [True]*size_corpus
if selected:
selected_test = [False]*size_corpus
for ix in range(len(selected)):
selected_test[ix]=True
return selected
cpdef np.ndarray compare_old(self,list listgs, list selected):
pass
cpdef np.ndarray compare(self,list graph_list, list selected): cpdef np.ndarray compare(self,list graph_list, list selected):
""" """
Return the similarity/distance matrix using the current algorithm. Return the similarity/distance matrix using the current algorithm.
......
...@@ -16,3 +16,4 @@ cdef class AbstractGraphEditDistance(Base): ...@@ -16,3 +16,4 @@ cdef class AbstractGraphEditDistance(Base):
cdef double insert_cost(self, int i, int j, nodesH, H) cdef double insert_cost(self, int i, int j, nodesH, H)
cdef double delete_cost(self, int i, int j, nodesG, G) cdef double delete_cost(self, int i, int j, nodesG, G)
cpdef double substitute_cost(self, node1, node2, G, H) cpdef double substitute_cost(self, node1, node2, G, H)
...@@ -4,14 +4,18 @@ from __future__ import print_function ...@@ -4,14 +4,18 @@ from __future__ import print_function
import sys import sys
import warnings import warnings
import numpy as np import numpy as np
cimport numpy as np
try: try:
from munkres import munkres from munkres import munkres
except ImportError: except ImportError:
warnings.warn("To obtain optimal results install the Cython 'munkres' module at https://github.com/jfrelinger/cython-munkres-wrapper") warnings.warn("To obtain optimal results install the Cython 'munkres' module at https://github.com/jfrelinger/cython-munkres-wrapper")
from scipy.optimize import linear_sum_assignment as munkres from scipy.optimize import linear_sum_assignment as munkres
cimport numpy as np
from ..base cimport Base from ..base cimport Base
import networkx as nx import networkx as nx
from ..helpers.general import parsenx2graph
from cython.parallel cimport prange,parallel
cdef class AbstractGraphEditDistance(Base): cdef class AbstractGraphEditDistance(Base):
...@@ -90,7 +94,7 @@ cdef class AbstractGraphEditDistance(Base): ...@@ -90,7 +94,7 @@ cdef class AbstractGraphEditDistance(Base):
cpdef double substitute_cost(self, node1, node2, G, H): cpdef double substitute_cost(self, node1, node2, G, H):
raise NotImplementedError raise NotImplementedError
cpdef np.ndarray compare(self,list listgs, list selected): cpdef np.ndarray compare_old(self,list listgs, list selected):
cdef int n = len(listgs) cdef int n = len(listgs)
cdef np.ndarray comparison_matrix = np.zeros((n, n)).astype(float) cdef np.ndarray comparison_matrix = np.zeros((n, n)).astype(float)
cdef int i,j cdef int i,j
...@@ -105,3 +109,23 @@ cdef class AbstractGraphEditDistance(Base): ...@@ -105,3 +109,23 @@ cdef class AbstractGraphEditDistance(Base):
#comparison_matrix[j, i] = comparison_matrix[i, j] #comparison_matrix[j, i] = comparison_matrix[i, j]
np.fill_diagonal(comparison_matrix,0) np.fill_diagonal(comparison_matrix,0)
return comparison_matrix return comparison_matrix
cpdef np.ndarray compare(self,list listgs, list selected):
cdef int n = len(listgs)
cdef double[:,:] comparison_matrix = np.zeros((n, n))
listgs=parsenx2graph(listgs)
cdef long[:] n_nodes = np.array([g.size() for g in listgs])
cdef bint[:] selected_test = self.get_selected_array(selected,n)
cdef int i,j
val=np.inf
with nogil, parallel(num_threads=8):
for i in prange(n,schedule='static'):
for j in range(n):
if n_nodes[i]>0 and n_nodes[j]>0 and selected_test[i] :
with gil:
comparison_matrix[i][j] = self.distance_ged(listgs[i],listgs[j])
else:
comparison_matrix[i][j] = 0
#comparison_matrix[j, i] = comparison_matrix[i, j]
return np.array(comparison_matrix)
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
import numpy as np import numpy as np
cimport numpy as np cimport numpy as np
from ..base cimport Base from ..base cimport Base
from cython.parallel cimport prange,parallel
from ..helpers.general import parsenx2graph
cdef class BP_2(Base): cdef class BP_2(Base):
...@@ -32,7 +33,7 @@ cdef class BP_2(Base): ...@@ -32,7 +33,7 @@ cdef class BP_2(Base):
self.edge_del = edge_del self.edge_del = edge_del
self.edge_ins = edge_ins self.edge_ins = edge_ins
cpdef np.ndarray compare(self,list listgs, list selected): cpdef np.ndarray compare_old(self,list listgs, list selected):
cdef int n = len(listgs) cdef int n = len(listgs)
cdef np.ndarray comparison_matrix = np.zeros((n, n)).astype(float) cdef np.ndarray comparison_matrix = np.zeros((n, n)).astype(float)
cdef int i,j cdef int i,j
...@@ -48,6 +49,27 @@ cdef class BP_2(Base): ...@@ -48,6 +49,27 @@ cdef class BP_2(Base):
return comparison_matrix return comparison_matrix
cpdef np.ndarray compare(self,list listgs, list selected):
cdef int n = len(listgs)
cdef list new_gs=parsenx2graph(listgs)
cdef double[:,:] comparison_matrix = np.zeros((n, n))
cdef bint[:] selected_test = self.get_selected_array(selected,n)
cdef int i,j
cdef long[:] n_nodes = np.array([g.size() for g in new_gs])
cdef long[:] n_edges = np.array([g.density() for g in new_gs])
with nogil, parallel(num_threads=4):
for i in prange(n,schedule='static'):
for j in range(i,n):
if n_nodes[i] > 0 and n_nodes[j] > 0 and selected_test[i] == True:
with gil:
comparison_matrix[i, j] = self.bp2(new_gs[i], new_gs[j])
else:
comparison_matrix[i, j] = 0
comparison_matrix[j, i] = comparison_matrix[i, j]
return comparison_matrix
cdef double bp2(self, g1, g2): cdef double bp2(self, g1, g2):
""" """
...@@ -100,8 +122,8 @@ cdef class BP_2(Base): ...@@ -100,8 +122,8 @@ cdef class BP_2(Base):
list containing costs from the optimal edit path list containing costs from the optimal edit path
""" """
cdef list psi_=[] cdef list psi_=[]
cdef list nodes1 = list(g1.nodes) cdef list nodes1 = list(g1.nodes())
cdef list nodes2 = list(g2.nodes) cdef list nodes2 = list(g2.nodes())
for u in nodes1: for u in nodes1:
v=None v=None
for w in nodes2: for w in nodes2:
...@@ -125,9 +147,9 @@ cdef class BP_2(Base): ...@@ -125,9 +147,9 @@ cdef class BP_2(Base):
:param g2: Second Graph :param g2: Second Graph
:return: :return:
""" """
cdef np.ndarray min_sum = np.zeros(len(g1)) cdef np.ndarray min_sum = np.zeros(g1.size())
nodes1 = list(g1.nodes) nodes1 = list(g1.nodes())
nodes2 = list(g2.nodes) nodes2 = list(g2.nodes())
nodes2.extend([None]) nodes2.extend([None])
cdef np.ndarray min_i cdef np.ndarray min_i
for i in range(len(nodes1)): for i in range(len(nodes1)):
...@@ -178,8 +200,8 @@ cdef class BP_2(Base): ...@@ -178,8 +200,8 @@ cdef class BP_2(Base):
""" """
#if isinstance(g1, nx.MultiDiGraph): #if isinstance(g1, nx.MultiDiGraph):
cdef list edges1 = list(g1.edges(n1)) if n1 else [] cdef list edges1 = g1.get_edges_no(n1) if n1 else []
cdef list edges2 = list(g2.edges(n2)) if n2 else [] cdef list edges2 = g2.get_edges_no(n2) if n2 else []
cdef np.ndarray min_sum = np.zeros(len(edges1)) cdef np.ndarray min_sum = np.zeros(len(edges1))
edges2.extend([None]) edges2.extend([None])
......
...@@ -4,6 +4,7 @@ from .abstract_graph_edit_dist cimport AbstractGraphEditDistance ...@@ -4,6 +4,7 @@ from .abstract_graph_edit_dist cimport AbstractGraphEditDistance
cdef class GraphEditDistance(AbstractGraphEditDistance): cdef class GraphEditDistance(AbstractGraphEditDistance):
cpdef object relabel_cost(self, node1, node2, G, H)
cpdef double substitute_cost(self, node1, node2, G, H) cpdef double substitute_cost(self, node1, node2, G, H)
cdef double delete_cost(self, int i, int j, nodesG, G) cdef double delete_cost(self, int i, int j, nodesG, G)
cdef double insert_cost(self, int i, int j, nodesH, H) cdef double insert_cost(self, int i, int j, nodesH, H)
\ No newline at end of file
...@@ -7,6 +7,7 @@ import numpy as np ...@@ -7,6 +7,7 @@ import numpy as np
cimport numpy as np cimport numpy as np
from .abstract_graph_edit_dist cimport AbstractGraphEditDistance from .abstract_graph_edit_dist cimport AbstractGraphEditDistance
from ..base cimport intersection,union_ from ..base cimport intersection,union_
from ..graph cimport Graph
cdef class GraphEditDistance(AbstractGraphEditDistance): cdef class GraphEditDistance(AbstractGraphEditDistance):
...@@ -14,52 +15,43 @@ cdef class GraphEditDistance(AbstractGraphEditDistance): ...@@ -14,52 +15,43 @@ cdef class GraphEditDistance(AbstractGraphEditDistance):
def __init__(self,node_del,node_ins,edge_del,edge_ins,weighted=False): def __init__(self,node_del,node_ins,edge_del,edge_ins,weighted=False):
AbstractGraphEditDistance.__init__(self,node_del,node_ins,edge_del,edge_ins) AbstractGraphEditDistance.__init__(self,node_del,node_ins,edge_del,edge_ins)
self.weighted=weighted self.weighted=weighted
cpdef double substitute_cost(self, node1, node2, G, H): cpdef double substitute_cost(self, node1, node2, G, H):
return self.relabel_cost(node1, node2, G, H) return self.relabel_cost(node1, node2, G, H)
def add_edges(self,node1,node2,G): cpdef object relabel_cost(self, node1, node2, G, H):
R=nx.create_empty_copy(G)
try:
R.add_edges_from(G.edges(node1,node2))
except Exception as e:
# To counter bug with a None for attribute... weird ??
arr_=G.edges(node1,node2)
new_list=[]
for item in arr_:
new_list.append((item[0],item[1]))
R.add_edges_from(new_list)
return R
def relabel_cost(self, node1, node2, G, H):
## Si deux noeuds égaux ## Si deux noeuds égaux
if node1 == node2 and G.degree(node1) == H.degree(node2): if node1 == node2 and G.degree(node1) == H.degree(node2):
return 0.0 return 0.0
elif node1 == node2 and G.degree(node1) != H.degree(node2): elif node1 == node2 and G.degree(node1) != H.degree(node2):
R = self.add_edges(node1,node2,G) #R = Graph(self.add_edges(node1,node2,G),G.get_node_key(),G.get_egde_key())
R2 = self.add_edges(node1,node2,H) #R2 = Graph(self.add_edges(node1,node2,H),H.get_node_key(),H.get_egde_key())
inter_=intersection(R,R2).number_of_edges() #inter_= R.size_edge_intersect(R2)
add_diff=abs(R2.number_of_edges()-inter_) R=set(G.get_edges_no(node1))
del_diff=abs(R.number_of_edges()-inter_) R2=set(H.get_edges_no(node2))
inter_=R.intersection(R2)
add_diff=abs(len(R2)-len(inter_))#abs(R2.density()-inter_)
del_diff=abs(len(R)-len(inter_))#abs(R.density()-inter_)
return (add_diff*self.edge_ins)+(del_diff*self.edge_del) return (add_diff*self.edge_ins)+(del_diff*self.edge_del)
#si deux noeuds connectés #si deux noeuds connectés
if (node1,node2) in G.edges() or (node2,node1) in G.edges(): if G.has_edge(node1,node2) or G.has_edge(node2,node1):
return self.node_ins+self.node_del return self.node_ins+self.node_del
if not node2 in G: if not node2 in G.nodes():
nodesH=list(H.nodes()) nodesH=H.nodes()
index=nodesH.index(node2) index=list(nodesH).index(node2)
return self.node_del+self.node_ins+self.insert_cost(index,index,nodesH,H) return self.node_del+self.node_ins+self.insert_cost(index,index,nodesH,H)
return sys.maxsize return sys.maxsize
cdef double delete_cost(self, int i, int j, nodesG, G): cdef double delete_cost(self, int i, int j, nodesG, G):
if i == j: if i == j:
return self.node_del+(G.degree(nodesG[i],weight=("weight" if self.weighted else None))*self.edge_del) # Deleting a node implicate to delete in and out edges return self.node_del+(G.degree(nodesG[i],weight=True)*self.edge_del) # Deleting a node implicate to delete in and out edges
return sys.maxsize return sys.maxsize
cdef double insert_cost(self, int i, int j, nodesH, H): cdef double insert_cost(self, int i, int j, nodesH, H):
if i == j: if i == j:
deg=H.degree(nodesH[j],weight=("weight" if self.weighted else None)) deg=H.degree(nodesH[j],weight=True)
if isinstance(deg,dict):deg=0 if isinstance(deg,dict):deg=0
return self.node_ins+(deg*self.edge_ins) return self.node_ins+(deg*self.edge_ins)
else: else:
......
# -*- coding: UTF-8 -*-
import sys
import networkx as nx
import numpy as np
cimport numpy as np
from .abstract_graph_edit_dist cimport AbstractGraphEditDistance
from ..base cimport intersection,union_
from ..graph cimport Graph
cdef class GraphEditDistance(AbstractGraphEditDistance):
def __init__(self,node_del,node_ins,edge_del,edge_ins,weighted=False):
AbstractGraphEditDistance.__init__(self,node_del,node_ins,edge_del,edge_ins)
self.weighted=weighted
cpdef double substitute_cost(self, node1, node2, G, H):
return self.relabel_cost(node1, node2, G, H)
def add_edges(self,node1,node2,G):
R=nx.create_empty_copy(G.get_nx())
try:
R.add_edges_from(G.edges(node1,node2))
except Exception as e:
# To counter bug with a None for attribute... weird ??
arr_=G.edges(node1,node2)
new_list=[]
for item in arr_:
new_list.append((item[0],item[1]))
R.add_edges_from(new_list)
return R
cpdef relabel_cost(self, node1, node2, G, H):
## Si deux noeuds égaux
if node1 == node2 and G.degree(node1) == H.degree(node2):
return 0.0
elif node1 == node2 and G.degree(node1) != H.degree(node2):
R = Graph(self.add_edges(node1,node2,G),G.get_node_key(),G.get_egde_key())
R2 = Graph(self.add_edges(node1,node2,H),H.get_node_key(),H.get_egde_key())
inter_= R.size_edge_intersect(R2)
add_diff=abs(R2.density()-inter_)
del_diff=abs(R.density()-inter_)
return (add_diff*self.edge_ins)+(del_diff*self.edge_del)
#si deux noeuds connectés
if G.has_edge(*(node1,node2)) or G.has_edge(*(node2,node1)):
return self.node_ins+self.node_del
if not node2 in G:
nodesH=H.nodes()
index=list(nodesH).index(node2)
return self.node_del+self.node_ins+self.insert_cost(index,index,nodesH,H)
return sys.maxsize
cdef double delete_cost(self, int i, int j, nodesG, G):
if i == j:
return self.node_del+(G.degree(nodesG[i],weight=True)*self.edge_del) # Deleting a node implicate to delete in and out edges
return sys.maxsize
cdef double insert_cost(self, int i, int j, nodesH, H):
if i == j:
deg=H.degree(nodesH[j],weight=True)
if isinstance(deg,dict):deg=0
return self.node_ins+(deg*self.edge_ins)
else:
return sys.maxsize
\ No newline at end of file
...@@ -4,6 +4,7 @@ import sys ...@@ -4,6 +4,7 @@ import sys
from .graph_edit_dist cimport GraphEditDistance from .graph_edit_dist cimport GraphEditDistance
import numpy as np import numpy as np
cimport numpy as np cimport numpy as np
from cython.parallel cimport prange,parallel
cdef class GreedyEditDistance(GraphEditDistance): cdef class GreedyEditDistance(GraphEditDistance):
""" """
...@@ -20,15 +21,6 @@ cdef class GreedyEditDistance(GraphEditDistance): ...@@ -20,15 +21,6 @@ cdef class GreedyEditDistance(GraphEditDistance):
cdef list edit_costs(self, G, H): cdef list edit_costs(self, G, H):
cdef np.ndarray cost_matrix=self.create_cost_matrix(G,H) cdef np.ndarray cost_matrix=self.create_cost_matrix(G,H)
"""
cdef np.ndarray cost_matrix_2=cost_matrix.copy()
cdef list psi=[]
for i in range(len(cost_matrix)):
phi_i=np.argmin((cost_matrix[i]))
cost_matrix=np.delete(cost_matrix,phi_i,1)
psi.append([i,phi_i+i]) #+i to compensate the previous column deletion
return [cost_matrix_2[psi[i][0]][psi[i][1]] for i in range(len(psi))]
"""
cdef np.ndarray cost_matrix_2=cost_matrix.copy().astype(np.double) cdef np.ndarray cost_matrix_2=cost_matrix.copy().astype(np.double)
cdef list psi=[] cdef list psi=[]
for i in range(len(cost_matrix)): for i in range(len(cost_matrix)):
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
import numpy as np import numpy as np
cimport numpy as np cimport numpy as np
from ..base cimport Base from ..base cimport Base
from cython.parallel cimport prange,parallel
from ..helpers.general import parsenx2graph
cdef class HED(Base): cdef class HED(Base):
""" """
...@@ -27,7 +29,7 @@ cdef class HED(Base): ...@@ -27,7 +29,7 @@ cdef class HED(Base):
self.edge_ins = edge_ins self.edge_ins = edge_ins
cpdef np.ndarray compare(self,list listgs, list selected): cpdef np.ndarray compare_old(self,list listgs, list selected):
cdef int n = len(listgs) cdef int n = len(listgs)
cdef np.ndarray comparison_matrix = np.zeros((n, n)).astype(float) cdef np.ndarray comparison_matrix = np.zeros((n, n)).astype(float)
cdef int i,j cdef int i,j
...@@ -42,6 +44,27 @@ cdef class HED(Base): ...@@ -42,6 +44,27 @@ cdef class HED(Base):
comparison_matrix[j, i] = comparison_matrix[i, j] comparison_matrix[j, i] = comparison_matrix[i, j]
return comparison_matrix return comparison_matrix
cpdef np.ndarray compare(self,list listgs, list selected):
cdef int n = len(listgs)
cdef list new_gs=parsenx2graph(listgs)
cdef double[:,:] comparison_matrix = np.zeros((n, n))
cdef bint[:] selected_test = self.get_selected_array(selected,n)
cdef int i,j
cdef long[:] n_nodes = np.array([g.size() for g in new_gs])
cdef long[:] n_edges = np.array([g.density() for g in new_gs])
with nogil, parallel(num_threads=4):
for i in prange(n,schedule='static'):
for j in range(i,n):
if n_nodes[i] > 0 and n_nodes[j] > 0 and selected_test[i] == True:
with gil:
comparison_matrix[i, j] = self.hed(new_gs[i], new_gs[j])
else:
comparison_matrix[i, j] = 0
comparison_matrix[j, i] = comparison_matrix[i, j]
return comparison_matrix
cdef float hed(self, g1, g2): cdef float hed(self, g1, g2):
...@@ -61,8 +84,8 @@ cdef class HED(Base): ...@@ -61,8 +84,8 @@ cdef class HED(Base):
:return: :return:
""" """
cdef np.ndarray min_sum = np.zeros(len(g1)) cdef np.ndarray min_sum = np.zeros(len(g1))
nodes1 = list(g1.nodes) nodes1 = list(g1.nodes())
nodes2 = list(g2.nodes) nodes2 = list(g2.nodes())
nodes2.extend([None]) nodes2.extend([None])
cdef np.ndarray min_i cdef np.ndarray min_i
for i in range(len(nodes1)): for i in range(len(nodes1)):
...@@ -113,8 +136,8 @@ cdef class HED(Base): ...@@ -113,8 +136,8 @@ cdef class HED(Base):
""" """
#if isinstance(g1, nx.MultiDiGraph): #if isinstance(g1, nx.MultiDiGraph):
cdef list edges1 = list(g1.edges(n1)) if n1 else [] cdef list edges1 = g1.get_edges_no(n1) if n1 else []
cdef list edges2 = list(g2.edges(n2)) if n2 else [] cdef list edges2 = g2.get_edges_no(n2) if n2 else []
cdef np.ndarray min_sum = np.zeros(len(edges1)) cdef np.ndarray min_sum = np.zeros(len(edges1))
edges2.extend([None]) edges2.extend([None])
......
...@@ -38,6 +38,7 @@ cdef class Graph: ...@@ -38,6 +38,7 @@ cdef class Graph:
cdef dict degree_per_attr # degree information per attr val cdef dict degree_per_attr # degree information per attr val
cdef dict degree_per_attr_weighted # degree information per attr val cdef dict degree_per_attr_weighted # degree information per attr val
cdef list attr_nodes # list of attr(dict) values for each node cdef list attr_nodes # list of attr(dict) values for each node
cdef dict edges_of_nodes # list of egdes connected to each node
# EDGES ATTRIBUTES # EDGES ATTRIBUTES
################## ##################
...@@ -107,7 +108,8 @@ cdef class Graph: ...@@ -107,7 +108,8 @@ cdef class Graph:
## GETTER ## GETTER
######### #########
cpdef list get_edges_(self,e1,e2) cpdef list get_edges_ed(self,str e1, str e2)
cpdef list get_edges_no(self,str n)
cpdef set get_edges_hash(self) cpdef set get_edges_hash(self)
cpdef set get_nodes_hash(self) cpdef set get_nodes_hash(self)
......
...@@ -59,7 +59,9 @@ cdef class Graph: ...@@ -59,7 +59,9 @@ cdef class Graph:
self.degree_per_attr_weighted={attr_v:{n:{"in":0,"out":0} for n in self.nodes_list} for attr_v in self.unique_edge_attr_vals} self.degree_per_attr_weighted={attr_v:{n:{"in":0,"out":0} for n in self.nodes_list} for attr_v in self.unique_edge_attr_vals}
# Retrieving Degree Information # Retrieving Degree Information
self.edges_of_nodes={}
for n in self.nodes_list: for n in self.nodes_list:
self.edges_of_nodes[n]=[self.hash_edge_attr(e1,e2,attr_dict[self.edge_attr_key]) if self.is_edge_attr else self.hash_edge(e1,e2) for e1,e2,attr_dict in G.edges(n,data=True)]
degree_all.append(G.degree(n)) degree_all.append(G.degree(n))
degree_all_weighted.append(G.degree(n,weight="weight")) degree_all_weighted.append(G.degree(n,weight="weight"))
if self.is_directed: if self.is_directed:
...@@ -161,12 +163,12 @@ cdef class Graph: ...@@ -161,12 +163,12 @@ cdef class Graph:
cpdef bint has_edge(self,str n_id1,str n_id2): cpdef bint has_edge(self,str n_id1,str n_id2):
if self.is_directed: if self.is_directed:
if n_id1 in self.edges_hash_map and n_id2 in self.edges_hash_map[n_id1][n_id2]: if n_id1 in self.edges_hash_map and n_id2 in self.edges_hash_map[n_id1]:
return True return True
else: else:
if n_id1 in self.edges_hash_map and n_id2 in self.edges_hash_map[n_id1][n_id2]: if n_id1 in self.edges_hash_map and n_id2 in self.edges_hash_map[n_id1]:
return True return True
if n_id2 in self.edges_hash_map and n_id1 in self.edges_hash_map[n_id2][n_id1]: if n_id2 in self.edges_hash_map and n_id1 in self.edges_hash_map[n_id2]:
return True return True
return False return False
...@@ -199,12 +201,14 @@ cdef class Graph: ...@@ -199,12 +201,14 @@ cdef class Graph:
else: else:
return self.edges_list return self.edges_list
cpdef list get_edges_(self,e1,e2): cpdef list get_edges_ed(self,str e1,str e2):
if self.is_edge_attr: if self.is_edge_attr:
hashes=self.edges_hash_map[e1][e2] hashes=self.edges_hash_map[e1][e2]
return [(e1,e2,self.edges_attr_list[self.edges_hash_idx[hash_]])for hash_ in hashes] return [(e1,e2,self.edges_attr_list[self.edges_hash_idx[hash_]])for hash_ in hashes]
else: else:
return [(e1,e2,None)] return [(e1,e2,None)]
cpdef list get_edges_no(self,str n):
return self.edges_of_nodes[n]
cpdef dict get_edge_attr(self,edge_hash): cpdef dict get_edge_attr(self,edge_hash):
return self.edges_attr_list[self.edges_hash_idx[edge_hash]] return self.edges_attr_list[self.edges_hash_idx[edge_hash]]
......
from ..graph cimport Graph
import networkx as nx
def parsenx2graph(list_gs):
new_gs=[nx.relabel_nodes(g,{node:str(node) for node in list(g.nodes)},copy=True) for g in list_gs]
new_gs=[Graph(g) for g in new_gs]
return new_gs
...@@ -5,14 +5,16 @@ cimport numpy as np ...@@ -5,14 +5,16 @@ cimport numpy as np
from .base cimport Base from .base cimport Base
from .base cimport intersection,union_ from .base cimport intersection,union_
from ..helpers.general import parsenx2graph
from cython.parallel cimport prange,parallel
cdef class Jaccard(Base): cdef class Jaccard(Base):
def __init__(self): def __init__(self):
Base.__init__(self,0,True) Base.__init__(self,0,True)
cpdef np.ndarray compare(self,list listgs, list selected):
cpdef np.ndarray compare_old(self,list listgs, list selected):
cdef int n = len(listgs) cdef int n = len(listgs)
cdef np.ndarray comparison_matrix = np.zeros((n, n)) cdef np.ndarray comparison_matrix = np.zeros((n, n))
cdef int i,j cdef int i,j
...@@ -37,5 +39,38 @@ cdef class Jaccard(Base): ...@@ -37,5 +39,38 @@ cdef class Jaccard(Base):
return comparison_matrix return comparison_matrix
cpdef np.ndarray compare(self,list listgs, list selected):
cdef int n = len(listgs)
cdef list new_gs=parsenx2graph(listgs)
cdef double[:,:] comparison_matrix = np.zeros((n, n))
cdef long[:] n_nodes = np.array([g.size() for g in new_gs])
cdef long[:] n_edges = np.array([g.density() for g in new_gs])
cdef int i,j
cdef bint[:] selected_test = self.get_selected_array(selected,n)