def test_is_aperiodic_disconnected(): #disconnected graph G = nx.DiGraph() G.add_cycle([1,2,3,4]) G.add_cycle([5,6,7,8]) assert_false(nx.is_aperiodic(G)) G.add_edge(1,3) G.add_edge(5,7) assert_true(nx.is_aperiodic(G))
def test_is_aperiodic_disconnected(): # disconnected graph G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) nx.add_cycle(G, [5, 6, 7, 8]) assert_false(nx.is_aperiodic(G)) G.add_edge(1, 3) G.add_edge(5, 7) assert_true(nx.is_aperiodic(G))
def test_is_aperiodic_disconnected(): # disconnected graph G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) nx.add_cycle(G, [5, 6, 7, 8]) assert not nx.is_aperiodic(G) G.add_edge(1, 3) G.add_edge(5, 7) assert nx.is_aperiodic(G)
def is_periodic(mat): """Check if the transition matrix is periodic. A matrix is periodic if it has a period greater than `2`, that is, if it """ graph = nx.DiGraph(mat) return not(nx.is_aperiodic(graph))
def output_aperiodicity_info(graph, path): """Output aperiodicity information about the graph. graph : (networkx.Graph) path: (String) contains the path to the output file """ with open(path, 'w') as out: out.write('***Aperiodicity***\n') out.write('Is aperiodic: %s' % nx.is_aperiodic(graph))
def output_aperiodicity_info (graph, path): """Output aperiodicity information about the graph. graph : (networkx.Graph) path: (String) contains the path to the output file """ with open(path, 'w') as out: out.write('***Aperiodicity***\n') out.write('Is aperiodic: %s' % nx.is_aperiodic(graph))
def is_aperiodic(G): """Return True if G is aperiodic. A directed graph is aperiodic if there is no integer k > 1 that divides the length of every cycle in the graph. Parameters ---------- G : NetworkX DiGraph Graph Returns ------- aperiodic : boolean True if the graph is aperiodic False otherwise Raises ------ NetworkXError If G is not directed Notes ----- This uses the method outlined in [1]_, which runs in O(m) time given m edges in G. Note that a graph is not aperiodic if it is acyclic as every integer trivial divides length 0 cycles. References ---------- .. [1] Jarvis, J. P.; Shier, D. R. (1996), Graph-theoretic analysis of finite Markov chains, in Shier, D. R.; Wallenius, K. T., Applied Mathematical Modeling: A Multidisciplinary Approach, CRC Press. """ if not G.is_directed(): raise nx.NetworkXError( "is_aperiodic not defined for undirected graphs") s = next(G.nodes_iter()) levels = {s: 0} this_level = [s] g = 0 l = 1 while this_level: next_level = [] for u in this_level: for v in G[u]: if v in levels: # Non-Tree Edge g = gcd(g, levels[u] - levels[v] + 1) else: # Tree Edge next_level.append(v) levels[v] = l this_level = next_level l += 1 if len(levels) == len(G): # All nodes in tree return g == 1 else: return g == 1 and nx.is_aperiodic(G.subgraph(set(G) - set(levels)))
def is_aperiodic(G): """Return True if G is aperiodic. A directed graph is aperiodic if there is no integer k > 1 that divides the length of every cycle in the graph. Parameters ---------- G : NetworkX DiGraph Graph Returns ------- aperiodic : boolean True if the graph is aperiodic False otherwise Raises ------ NetworkXError If G is not directed Notes ----- This uses the method outlined in [1]_, which runs in O(m) time given m edges in G. Note that a graph is not aperiodic if it is acyclic as every integer trivial divides length 0 cycles. References ---------- .. [1] Jarvis, J. P.; Shier, D. R. (1996), Graph-theoretic analysis of finite Markov chains, in Shier, D. R.; Wallenius, K. T., Applied Mathematical Modeling: A Multidisciplinary Approach, CRC Press. """ if not G.is_directed(): raise nx.NetworkXError( "is_aperiodic not defined for undirected graphs") s = arbitrary_element(G) levels = {s: 0} this_level = [s] g = 0 l = 1 while this_level: next_level = [] for u in this_level: for v in G[u]: if v in levels: # Non-Tree Edge g = gcd(g, levels[u] - levels[v] + 1) else: # Tree Edge next_level.append(v) levels[v] = l this_level = next_level l += 1 if len(levels) == len(G): # All nodes in tree return g == 1 else: return g == 1 and nx.is_aperiodic(G.subgraph(set(G) - set(levels)))
def test_networkx_methods(): reducible_G = nx.DiGraph(np.matrix([[1,0],[0,1]])) print 'reducible- is strongly connected? ' + str(nx.is_strongly_connected(reducible_G)) #False print 'reducible- strongly connected components: ' + str(nx.strongly_connected_components(reducible_G)) #[[0], [1]] print 'reducible- is aperiodic? ' + str(nx.is_aperiodic(reducible_G)) #True irreducible_periodic_G = nx.DiGraph(np.matrix([[0,1],[1,0]])) print '\nirreducible_periodic- is strongly connected? ' + str(nx.is_strongly_connected(irreducible_periodic_G)) #True print 'irreducible_periodic- strongly connected components: ' + str(nx.strongly_connected_components(irreducible_periodic_G)) #[[0, 1]] print 'irreducible_periodic- is aperiodic? ' + str(nx.is_aperiodic(irreducible_periodic_G)) #False (2) ergodic_G = nx.DiGraph(np.matrix([[0,1,1,0],[1,0,0,1],[0,1,0,0],[0,1,0,0]])) modified_G = nx.DiGraph(salsa.get_matrix(ergodic_G, mat_type='hub', sparse=False)) print 'modified- is strongly connected? ' + str(nx.is_strongly_connected(modified_G)) #False print 'modified- strongly connected components: ' + str(nx.strongly_connected_components(modified_G)) #[[0, 2, 3], [1]] print 'modified- is aperiodic? ' + str(nx.is_aperiodic(modified_G)) #True return
def test_eig_error(): #graph_file = '/home/michal/SALSA_files/tmp/real_run/graph_11' #G = gm.read_graph_from_file(graph_file) graph_list = [(354, 354, {'weight': 0.5}),\ (354, 13291, {'weight': 0.25}),\ (354, 11354, {'weight': 0.25}),\ (15204, 15204, {'weight': 0.5}),\ (15204, 14639, {'weight': 0.5}),\ (11210, 6898, {'weight': 0.25}),\ (11210, 11210, {'weight': 0.5}),\ (11210, 11354, {'weight': 0.25}),\ (13291, 354, {'weight': 0.5}),\ (13291, 13291, {'weight': 0.5}),\ (14639, 13236, {'weight': 0.16666666666666666}),\ (14639, 6898, {'weight': 0.16666666666666666}),\ (14639, 15204, {'weight': 0.25}),\ (14639, 14639, {'weight': 0.41666666666666663}),\ (6898, 6898, {'weight': 0.6111111111111112}),\ (6898, 13236, {'weight': 0.1111111111111111}),\ (6898, 11210, {'weight': 0.16666666666666666}),\ (6898, 14639, {'weight': 0.1111111111111111}),\ (13236, 6898, {'weight': 0.3333333333333333}),\ (13236, 13236, {'weight': 0.3333333333333333}),\ (13236, 14639, {'weight': 0.3333333333333333}),\ (11354, 11210, {'weight': 0.25}),\ (11354, 354, {'weight': 0.25}),\ (11354, 11354, {'weight': 0.5})] #(11354, 11354, {'weight': 0.5})] G = nx.DiGraph(graph_list) #print G.edges(data=True) print '--- eig_calc: is sub graph stochastic? ' + str(gm.check_if_stochastic_matrix(nx.to_numpy_matrix(G)))#; sys.stdout.flush() print '--- eig_calc: is sub graph strongly connected? ' + str(nx.is_strongly_connected(G))#; sys.stdout.flush() print '--- eig_calc: is sub graph aperiodic? ' + str(nx.is_aperiodic(G));# sys.stdout.flush() #np_mat = nx.to_numpy_matrix(G) #print 'det= '+ str(np.linalg.det(np_mat)) print salsa.eig_calc(G) '''try: print salsa.eig_calc(G) except RuntimeError: max_weight = max(e[2]['weight'] for e in G.edges_iter(data=True)) noise = 1e-13 for e in G.edges_iter(data=True): if e[2]['weight'] == max_weight: e[2]['weight'] += noise if not gm.check_if_stochastic_matrix(nx.to_numpy_matrix(G)): nx.stochastic_graph(G, copy=False) print salsa.eig_calc(G)''' return
def directed_laplacian_matrix(G, nodelist=None, weight='weight', walk_type=None, alpha=0.95): import scipy as sp from scipy.sparse import identity, spdiags, linalg if walk_type is None: if nx.is_strongly_connected(G): if nx.is_aperiodic(G): walk_type = "random" else: walk_type = "lazy" else: walk_type = "pagerank" M = nx.to_scipy_sparse_matrix(G, nodelist=nodelist, weight=weight, dtype=float) n, m = M.shape if walk_type in ["random", "lazy"]: DI = spdiags(1.0 / sp.array(M.sum(axis=1).flat), [0], n, n) if walk_type == "random": P = DI * M else: I = identity(n) P = (I + DI * M) / 2.0 elif walk_type == "pagerank": if not (0 < alpha < 1): raise nx.NetworkXError('alpha must be between 0 and 1') M = M.todense() dangling = sp.where(M.sum(axis=1) == 0) for d in dangling[0]: M[d] = 1.0 / n M = M / M.sum(axis=1) P = alpha * M + (1 - alpha) / n else: raise nx.NetworkXError("walk_type must be random, lazy, or pagerank") evals, evecs = linalg.eigs(P.T, k=1, tol=1E-2) v = evecs.flatten().real p = v / v.sum() sqrtp = sp.sqrt(p) Q = spdiags(sqrtp, [0], n, n) * P * spdiags(1.0 / sqrtp, [0], n, n) I = sp.identity(len(G)) return I - (Q + Q.T) / 2.0
def print_is_of_type_attrs(graph): print("\n====== is of type X? ======") print("Directed? ->", "Yes" if nx.is_directed(graph) else "No") print("Directed acyclic? ->", "Yes" if nx.is_directed_acyclic_graph(graph) else "No") print("Weighted? ->", "Yes" if nx.is_weighted(graph) else "No") if nx.is_directed(graph): print("Aperiodic? ->", "Yes" if nx.is_aperiodic(graph) else "No") print("Arborescence? ->", "Yes" if nx.is_arborescence(graph) else "No") print("Weakly Connected? ->", "Yes" if nx.is_weakly_connected(graph) else "No") print("Semi Connected? ->", "Yes" if nx.is_semiconnected(graph) else "No") print("Strongly Connected? ->", "Yes" if nx.is_strongly_connected(graph) else "No") else: print("Connected? ->", "Yes" if nx.is_connected(graph) else "No") print("Bi-connected? ->", "Yes" if nx.is_biconnected(graph) else "No") if not graph.is_multigraph(): print("Chordal? -> ", "Yes" if nx.is_chordal(graph) else "No") print("Forest? -> ", "Yes" if nx.is_chordal(graph) else "No") print("Distance regular? -> ", "Yes" if nx.is_distance_regular(graph) else "No") print("Eulerian? -> ", "Yes" if nx.is_eulerian(graph) else "No") print("Strongly regular? -> ", "Yes" if nx.is_strongly_regular(graph) else "No") print("Tree? -> ", "Yes" if nx.is_tree(graph) else "No")
def test_is_aperiodic_selfloop(): G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) G.add_edge(1, 1) assert nx.is_aperiodic(G)
def power_iteration(G,max_iter=100,tol=1.0e-8,normalize=None,nstart=None,nstart_norm=None): ''' Calculates the steady state of graph using power method. In formal we use it when graph size is 2... Parameters ---------- G - networkx directed graph, the strongly connected component (subGraph) in our case max_iter - int, max iterations tol - float , the tolerance normalize - int, the number of nodes in the original (entire) graph- for normlizing the resulted eigenvector as per the proportion of the component from the entire (original) graph nstart - list of floats - the initial vector. nstart_norm - float, the weight [0,1] for normalizing the resulted eigenvector (for referring the risk proportion of the component from the entire (original) graph). *NOTE: normalize and nstart_norm cannot come together!! only one of them can be different from None! nstart and nstart_norm are not related to each other! Returns ------- results_dict - a dict of the (normalized) dominant eigenvector (the keys are G nodes names- basically integer) ''' import scipy#.sparse #import numpy as np startTime = datetime.now() n=nx.number_of_nodes(G) A=nx.to_scipy_sparse_matrix(G) if nstart is None: x=(scipy.ones((n,1))/n).T # initial guess else: #x=np.asarray(nstart_dict.values()).flatten() # IN MY CASE: is it the init of hubs or authorities?? x=np.asarray(nstart) # normalize starting vector s=1.0/x.sum() for k in x: x[k]*=s # power iteration on authority matrix i=0 while True: xlast=x x=x*A # we multiple from left for extracting the matrix row x=x/x.max() # check convergence, l1 norm err=scipy.absolute(x-xlast).sum() if err < tol: break if i>max_iter: # in general- this method is used when there are only 2 nodes in the class # if the graph is aperiodic than the vector we got after max_iter is good eanough if nx.is_aperiodic(G): print '(salsa) power_iteration: (APERIODIC CLASS- ',n,' nodes) failed to converge in %d iterations, continues with the last vector!!!'%(i+1) break else: #the class is periodic print '(salsa) power_iteration: (',n,' nodes) PERIODIC CLASS!!!' raise NetworkXError("(salsa) power_iteration: (PERIODIC CLASS) power iteration failed to converge in %d iterations."%(i+1)) i+=1 results=np.asarray(x).flatten() results = results/results.sum() if normalize: norm_factor = float(G.number_of_nodes())/normalize results = results*norm_factor elif nstart_norm != None: results = results*nstart_norm results_dict = dict(zip(G.nodes(),map(float,results))) #if n > 100: print '--- power_iteration: calc of class contains '+str(n)+' nodes, ('+str(float(n)/normalize)+'% of the main graph) took-'+str(datetime.now()-startTime); sys.stdout.flush() return results_dict
def is_aperiodic(mat): """Check if a stochastic matrix is aperiodic.""" graph = nx.DiGraph(mat) return nx.is_aperiodic(graph)
def salsa_scipy_old(G,max_iter=100,tol=1.0e-6,nstart_dict=None,normalized=True, debug=False): """Return HITS hubs and authorities values for nodes. The HITS algorithm computes two numbers for a node. Authorities estimates the node value based on the incoming links. Hubs estimates the node value based on outgoing links. Parameters ----------- G : graph A NetworkX graph max_iter : interger, optional Maximum number of iterations in power method. tol : float, optional Error tolerance used to check convergence in power method iteration. nstart : dictionary, optional Starting value of each node for power method iteration. normalized : bool (default=True) Normalize results by the sum of all of the values. Returns ------- (hubs,authorities) : two-tuple of dictionaries Two dictionaries keyed by node containing the hub and authority values. Examples -------- >>> G=nx.path_graph(4) >>> h,a=nx.hits(G) Notes ----- This implementation uses SciPy sparse matrices. The eigenvector calculation is done by the power iteration method and has no guarantee of convergence. The iteration will stop after max_iter iterations or an error tolerance of number_of_nodes(G)*tol has been reached. The HITS algorithm was designed for directed graphs but this algorithm does not check if the input graph is directed and will execute on undirected graphs. References ---------- .. [1] A. Langville and C. Meyer, "A survey of eigenvector methods of web information retrieval." http://citeseer.ist.psu.edu/713792.html .. [2] Jon Kleinberg, Authoritative sources in a hyperlinked environment Journal of the ACM 46 (5): 604-632, 1999. doi:10.1145/324133.324140. http://www.cs.cornell.edu/home/kleinber/auth.pdf. """ #import sys print '\n\t~~~~~~ salsa_scipy (G, max_iter='+str(max_iter)+', tol='+str(tol)+', nstart_dict, normalized='+str(normalized)+') ~~~~~~\n'; sys.stdout.flush() try: import scipy#.sparse as sp import numpy as np import sys except ImportError: raise ImportError(\ "hits_scipy() requires SciPy: http://scipy.org/") if len(G) == 0: return {},{} print '--- salsa_scipy: ' + str(datetime.now()); sys.stdout.flush(); startTime = datetime.now() ''''M=nx.to_scipy_sparse_matrix(G,nodelist=G.nodes()) (n,m)=M.shape # should be square A=M.T*M # authority matrix''' A=get_matrix(G,mat_type='authority',sparse=True,force_ergodicity=True, CN_name=10) (n,m)=A.shape # should be square if debug: new_G_h = nx.DiGraph(A) print '\n--- salsa_scipy_old: hub- is new graph stochastic? ' + str(gm.check_if_stochastic_matrix(nx.to_numpy_matrix(new_G_h))); sys.stdout.flush() print '--- salsa_scipy_old: hub- is new graph strongly connected? ' + str(nx.is_strongly_connected(new_G_h)); sys.stdout.flush() print '--- salsa_scipy_old: hub- is new graph aperiodic? ' + str(nx.is_aperiodic(new_G_h)); sys.stdout.flush() new_G_h.clear() #print '--- salsa_scipy_old: debug steps (hub) took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now(); sys.stdout.flush() print '--- salsa_scipy: get authority matrix took: ' + str(datetime.now()-startTime); sys.stdout.flush(); tmpTime = datetime.now() # choose fixed starting vector if not given if nstart_dict is None: a=scipy.ones((n,1))/n # initial guess else: a=np.asarray(nstart_dict.values()).flatten() # IN MY CASE: is it the init of hubs or authorities?? # normalize starting vector s=1.0/a.sum() for k in a: a[k]*=s # power iteration on authority matrix i=0 a=a.T L_c=get_matrix_norm_by_col(G,sparse=True) while True: alast=a #x=M*x a=a*A a=a/a.max() # check convergence, l1 norm err=scipy.absolute(a-alast).sum() if err < tol: break if i>max_iter: #raise NetworkXError("HITS: power iteration failed to converge in %d iterations."%(i+1)) ''''DEBUG:''' print '\n###\tSALSA_SCIPY: power iteration failed to converge in ' + str(i+1) + ' iterations- returns the current vectors' break i+=1 print '--- salsa_scipy: authorities vector calculation took: ' + str(datetime.now()-tmpTime) tmpTime = datetime.now() a=np.asarray(a).flatten() # h=M*a #h=np.asarray(M*a).flatten() h=np.asarray(L_c*a.T).flatten() #h=np.asarray(L_c*a).flatten() print '--- salsa_scipy: hubs vector calculation took: ' + str(datetime.now()-tmpTime) tmpTime = datetime.now() if normalized: h = h/h.sum() a = a/a.sum() print '--- salsa_scipy: vectors normalization took: ' + str(datetime.now()-tmpTime) hubs=dict(zip(G.nodes(),map(float,h))) authorities=dict(zip(G.nodes(),map(float,a))) #DEBUG- Print output: print '\nh after ' + str(i+1) + ' iterations:'; gm.print_dict_ordered_by_value(hubs); print '\na after ' + str(i+1) + ' iterations:'; gm.print_dict_ordered_by_value(authorities) print '--- salsa_scipy: all method took: ' + str(datetime.now()-startTime) return hubs,authorities
def test_is_aperiodic_cycle4(): G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) G.add_edge(1, 3) assert_true(nx.is_aperiodic(G))
def test_is_aperiodic_bipartite(): # Bipartite graph G = nx.DiGraph(nx.davis_southern_women_graph()) assert_false(nx.is_aperiodic(G))
def salsa_numpy(G,normalized=True): """Return HITS hubs and authorities values for nodes. The HITS algorithm computes two numbers for a node. Authorities estimates the node value based on the incoming links. Hubs estimates the node value based on outgoing links. Parameters ----------- G : graph A NetworkX graph normalized : bool (default=True) Normalize results by the sum of all of the values. Returns ------- (hubs,authorities) : two-tuple of dictionaries Two dictionaries keyed by node containing the hub and authority values. Examples -------- >>> G=nx.path_graph(4) >>> h,a=nx.hits(G) Notes ----- The eigenvector calculation uses NumPy's interface to LAPACK. The HITS algorithm was designed for directed graphs but this algorithm does not check if the input graph is directed and will execute on undirected graphs. References ---------- .. [1] A. Langville and C. Meyer, "A survey of eigenvector methods of web information retrieval." http://citeseer.ist.psu.edu/713792.html .. [2] Jon Kleinberg, Authoritative sources in a hyperlinked environment Journal of the ACM 46 (5): 604-32, 1999. doi:10.1145/324133.324140. http://www.cs.cornell.edu/home/kleinber/auth.pdf. """ print '\n\t~~~~~~ salsa_numpy (eigenvector calc) ~~~~~~\n' try: import numpy as np import scipy as sp except ImportError: raise ImportError(\ "hits_numpy() requires NumPy: http://scipy.org/") if len(G) == 0: return {},{} print '--- salsa_numpy: start time- ' + str(datetime.now()) startTime = datetime.now() #np.set_printoptions(precision=3) # For printing numpy objects- prints 3 decimal after the point. H_sparse = get_matrix(G,mat_type='hub',sparse=True) print '--- salsa_numpy: get_matrix (hub) took: '+str(datetime.now()-startTime); tmpTime = datetime.now() eps = gm.epsilon # DEBUG: new_G_h = nx.DiGraph(H_sparse) print 'is new graph strongly connected? ' + str(nx.is_strongly_connected(new_G_h)) print 'is new graph aperiodic? ' + str(nx.is_aperiodic(new_G_h)) #H = gm.convert_all_matrix_zeros_to_val(H_sparse, val=eps, stochastic_out=True) #print '--- salsa_numpy: convert_all_matrix_zeros_to_eps took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now() H = H_sparse.todense() #e,ev=np.linalg.eig(H) e,ev=sp.linalg.eig(H,left=True,right=False) #e,ev=np.linalg.eig(H.T) #we send H.T for calculating the LEFT eigenvector! print '--- salsa_numpy: calculating hub eigs took: ' + str(datetime.now()-tmpTime) #e,ev=sps.linalg.eigs(H,left=True,right=False) m=e.argsort()[-1] # index of maximum eigenvalue '''#DEBUG: print('\nH:\n' + str(H.round(3))) print'\ne rounded (3)\n' + str(e.round(3)) + '\nev rounded (3)\n' + str(ev.round(3)) print 'm- index of maximum eigenvalue= ' + str(m) + ', max eigenvalue= ' + str(e[m]) + \ '\nev rounded (3)\n' + str(np.array(ev[:,m]).flatten().round(3))''' h=np.array(ev[:,m]).flatten() # DEBUG: print h tmpTime = datetime.now() A_sparse = get_matrix(G,mat_type='authority',sparse=True) print '--- salsa_numpy: get_matrix (authority) took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now() new_G_a = nx.DiGraph(A_sparse) print 'is new graph strongly connected? ' + str(nx.is_strongly_connected(new_G_a)) print 'is new graph aperiodic? ' + str(nx.is_aperiodic(new_G_a)) #A = gm.convert_all_matrix_zeros_to_val(A_sparse, val=eps, stochastic_out=True) #print '--- salsa_numpy: convert_all_matrix_zeros_to_eps took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now() A = A_sparse.todense() e,ev=sp.linalg.eig(A,left=True,right=False) #e,ev=sps.linalg.eigs(A,left=True,right=False) #e,ev=np.linalg.eig(A.T) #we send A.T for calculating the LEFT eigenvector! print '--- salsa_numpy: calculating hub eigs took: ' + str(datetime.now()-tmpTime) m=e.argsort()[-1] # index of maximum eigenvalue a=np.array(ev[:,m]).flatten() '''#DEBUG: print('\n\nA:\n' + str(A.round(3))) print 'm- index of maximum eigenvalue= ' + str(m) + '\ne rounded (3)\n' + str(e.round(3)) + '\nev rounded (3)\n' + str(ev.round(3)) print('\nh before norm:' + str(h) + '\na before norm:' + str(a)) print 'max eigenvalue= ' + str(e[m]) + '\nev rounded (3)\n' + str(np.array(ev[:,m]).flatten().round(3))''' if normalized: h = h/h.sum() a = a/a.sum() else: h = h/h.max() a = a/a.max() hubs=dict(zip(G.nodes(),map(float,h))) authorities=dict(zip(G.nodes(),map(float,a))) return hubs,authorities
# components nx.is_strongly_connected(G) nx.number_strongly_connected_components(G) scc = nx.strongly_connected_components(G) nx.strongly_connected_components_recursive(G) nx.condensation(G, scc) # attracting components nx.is_attracting_component(G) nx.number_attracting_components(G) nx.attracting_components(G) # directed acyclic graphs nx.is_directed_acyclic_graph(G) nx.is_aperiodic(G) # distance measure (all for connected graph) nx.center(Gcc) nx.diameter(Gcc) nx.eccentricity(Gcc) nx.periphery(Gcc) nx.radius(Gcc) # flows (seg fault currently) #nx.max_flow(Gcc, 1, 2) #nx.min_cut(G, 1, 2) # isolates nx.is_isolate(G, 1) # False nx.is_isolate(G, 5) # True
def _transition_matrix(G, nodelist=None, weight="weight", walk_type=None, alpha=0.95): """Returns the transition matrix of G. This is a row stochastic giving the transition probabilities while performing a random walk on the graph. Depending on the value of walk_type, P can be the transition matrix induced by a random walk, a lazy random walk, or a random walk with teleportation (PageRank). Parameters ---------- G : DiGraph A NetworkX graph nodelist : list, optional The rows and columns are ordered according to the nodes in nodelist. If nodelist is None, then the ordering is produced by G.nodes(). weight : string or None, optional (default='weight') The edge data key used to compute each value in the matrix. If None, then each edge has weight 1. walk_type : string or None, optional (default=None) If None, `P` is selected depending on the properties of the graph. Otherwise is one of 'random', 'lazy', or 'pagerank' alpha : real (1 - alpha) is the teleportation probability used with pagerank Returns ------- P : NumPy matrix transition matrix of G. Raises ------ NetworkXError If walk_type not specified or alpha not in valid range """ import numpy as np import scipy as sp import scipy.sparse # call as sp.sparse if walk_type is None: if nx.is_strongly_connected(G): if nx.is_aperiodic(G): walk_type = "random" else: walk_type = "lazy" else: walk_type = "pagerank" A = nx.to_scipy_sparse_array(G, nodelist=nodelist, weight=weight, dtype=float) n, m = A.shape if walk_type in ["random", "lazy"]: # TODO: Rm csr_array wrapper when spdiags array creation becomes available DI = sp.sparse.csr_array( sp.sparse.spdiags(1.0 / A.sum(axis=1), 0, n, n)) if walk_type == "random": P = DI @ A else: # TODO: Rm csr_array wrapper when identity array creation becomes available I = sp.sparse.csr_array(sp.sparse.identity(n)) P = (I + DI @ A) / 2.0 elif walk_type == "pagerank": if not (0 < alpha < 1): raise nx.NetworkXError("alpha must be between 0 and 1") # this is using a dense representation. NOTE: This should be sparsified! A = A.toarray() # add constant to dangling nodes' row A[A.sum(axis=1) == 0, :] = 1 / n # normalize A = A / A.sum(axis=1)[np.newaxis, :].T P = alpha * A + (1 - alpha) / n else: raise nx.NetworkXError("walk_type must be random, lazy, or pagerank") return P
def _transition_matrix(G, nodelist=None, weight='weight', walk_type=None, alpha=0.95): """Returns the transition matrix of G. This is a row stochastic giving the transition probabilities while performing a random walk on the graph. Depending on the value of walk_type, P can be the transition matrix induced by a random walk, a lazy random walk, or a random walk with teleportation (PageRank). Parameters ---------- G : DiGraph A NetworkX graph nodelist : list, optional The rows and columns are ordered according to the nodes in nodelist. If nodelist is None, then the ordering is produced by G.nodes(). weight : string or None, optional (default='weight') The edge data key used to compute each value in the matrix. If None, then each edge has weight 1. walk_type : string or None, optional (default=None) If None, `P` is selected depending on the properties of the graph. Otherwise is one of 'random', 'lazy', or 'pagerank' alpha : real (1 - alpha) is the teleportation probability used with pagerank Returns ------- P : NumPy array transition matrix of G. Raises ------ NetworkXError If walk_type not specified or alpha not in valid range """ import scipy as sp from scipy.sparse import identity, spdiags if walk_type is None: if nx.is_strongly_connected(G): if nx.is_aperiodic(G): walk_type = "random" else: walk_type = "lazy" else: walk_type = "pagerank" M = nx.to_scipy_sparse_matrix(G, nodelist=nodelist, weight=weight, dtype=float) n, m = M.shape if walk_type in ["random", "lazy"]: DI = spdiags(1.0 / sp.array(M.sum(axis=1).flat), [0], n, n) if walk_type == "random": P = DI * M else: I = identity(n) P = (I + DI * M) / 2.0 elif walk_type == "pagerank": if not (0 < alpha < 1): raise nx.NetworkXError('alpha must be between 0 and 1') # this is using a dense representation M = M.todense() # add constant to dangling nodes' row dangling = sp.where(M.sum(axis=1) == 0) for d in dangling[0]: M[d] = 1.0 / n # normalize M = M / M.sum(axis=1) P = alpha * M + (1 - alpha) / n else: raise nx.NetworkXError("walk_type must be random, lazy, or pagerank") return P
def salsa_sparse(G, CN_name='CN', normalized=True, debug_mode=False): """Return HITS hubs and authorities values for nodes. The HITS algorithm computes two numbers for a node. Authorities estimates the node value based on the incoming links. Hubs estimates the node value based on outgoing links. Parameters ----------- G : graph A NetworkX graph normalized : bool (default=True) Normalize results by the sum of all of the values. Returns ------- (hubs,authorities) : two-tuple of dictionaries Two dictionaries keyed by node containing the hub and authority values. Examples -------- >>> G=nx.path_graph(4) >>> h,a=nx.hits(G) Notes ----- The eigenvector calculation uses NumPy's interface to LAPACK. The HITS algorithm was designed for directed graphs but this algorithm does not check if the input graph is directed and will execute on undirected graphs. References ---------- .. [1] A. Langville and C. Meyer, "A survey of eigenvector methods of web information retrieval." http://citeseer.ist.psu.edu/713792.html .. [2] Jon Kleinberg, Authoritative sources in a hyperlinked environment Journal of the ACM 46 (5): 604-32, 1999. doi:10.1145/324133.324140. http://www.cs.cornell.edu/home/kleinber/auth.pdf. """ print '\n\t~~~~~~ salsa_sparse (G, CN_name=' + str( CN_name) + ', normalized=' + str(normalized) + ', debug_mode=' + str( debug_mode) + ') ~~~~~~\n' try: #import numpy as np import scipy as sp import sys except ImportError: raise ImportError(\ "salsa_sparse() requires SciPy: http://scipy.org/") if len(G) == 0: return {}, {} print '--- salsa_sparse: start time- ' + str(datetime.now()) sys.stdout.flush() startTime = datetime.now() #np.set_printoptions(precision=3) # For printing numpy objects- prints 3 decimal after the point. print '--- salsa_sparse: hub- percentage of non-zero elements: ' + str( float(nx.to_scipy_sparse_matrix(G).getnnz()) / G.number_of_nodes()**2) sys.stdout.flush() H = get_matrix(G, mat_type='hub', sparse=True) print '--- salsa_sparse: get_matrix (hub) took: ' + str(datetime.now() - startTime) tmpTime = datetime.now() sys.stdout.flush() print '--- salsa_sparse: hub- percentage of non-zero elements: ' + str( float(H.getnnz()) / G.number_of_nodes()**2) sys.stdout.flush() eps = gm.epsilon H = gm.convert_SL_and_CN_weights_to_val(H, val=eps, CN_idx=G.nodes().index(CN_name), stochastic_out=True) print '\n--- salsa_sparse: convert_SL_and_CN_weights_to_val took: ' + str( datetime.now() - tmpTime) tmpTime = datetime.now() sys.stdout.flush() print '--- salsa_sparse: hub- percentage of non-zero elements: ' + str( float(H.getnnz()) / G.number_of_nodes()**2) sys.stdout.flush() if debug_mode: new_G_h = nx.DiGraph(H) print '\n--- salsa_sparse: hub- is new graph stochastic? ' + str( gm.check_if_stochastic_matrix(nx.to_numpy_matrix(new_G_h))) sys.stdout.flush() print '--- salsa_sparse: hub- is new graph strongly connected? ' + str( nx.is_strongly_connected(new_G_h)) sys.stdout.flush() print '--- salsa_sparse: hub- is new graph aperiodic? ' + str( nx.is_aperiodic(new_G_h)) sys.stdout.flush() new_G_h.clear() print '--- salsa_sparse: debug steps (hub) took: ' + str( datetime.now() - tmpTime) tmpTime = datetime.now() sys.stdout.flush() #H = gm.convert_all_matrix_zeros_to_val(H_sparse, val=eps, stochastic_out=True) e, h = sp.sparse.linalg.eigen.arpack.eigs(H.T, k=1, sigma=1, which='LM') print '\n--- salsa_sparse: calculating hub eigs took: ' + str( datetime.now() - tmpTime) sys.stdout.flush() tmpTime = datetime.now() A = get_matrix(G, mat_type='authority', sparse=True) print '--- salsa_sparse: get_matrix (authority) took: ' + str( datetime.now() - tmpTime) tmpTime = datetime.now() sys.stdout.flush() print '--- salsa_sparse: authority- percentage of non-zero elements: ' + str( float(A.getnnz()) / G.number_of_nodes()**2) sys.stdout.flush() A = gm.convert_SL_and_CN_weights_to_val(A, val=eps, CN_idx=G.nodes().index(CN_name), stochastic_out=True) print '\n--- salsa_sparse: convert_SL_and_CN_weights_to_val took: ' + str( datetime.now() - tmpTime) tmpTime = datetime.now() sys.stdout.flush() print '--- salsa_sparse: authority- percentage of non-zero elements: ' + str( float(A.getnnz()) / G.number_of_nodes()**2) sys.stdout.flush() if debug_mode: new_G_a = nx.DiGraph(A) print '\n--- salsa_sparse: hub- is new graph stochastic? ' + str( gm.check_if_stochastic_matrix(nx.to_numpy_matrix(new_G_a))) sys.stdout.flush() print '--- salsa_sparse: authority- is new graph strongly connected? ' + str( nx.is_strongly_connected(new_G_a)) sys.stdout.flush() print '--- salsa_sparse: authority- is new graph aperiodic? ' + str( nx.is_aperiodic(new_G_a)) sys.stdout.flush() new_G_a.clear() print '--- salsa_sparse: debug steps (authority) took: ' + str( datetime.now() - tmpTime) tmpTime = datetime.now() sys.stdout.flush() #A = gm.convert_all_matrix_zeros_to_val(A_sparse, val=eps, stochastic_out=True) #print '--- salsa_numpy: convert_all_matrix_zeros_to_eps took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now() e, a = sp.sparse.linalg.eigen.arpack.eigs(A.T, k=1, sigma=1, which='LM') print '\n--- salsa_sparse: calculating hub eigs took: ' + str( datetime.now() - tmpTime) sys.stdout.flush() if normalized: h = h / h.sum() a = a / a.sum() else: h = h / h.max() a = a / a.max() if (h.imag.sum() != 0. or a.imag.sum() != 0.): print '##### COMPLEX VECTOR!!!! returning the real part only!!! #####' sys.stdout.flush() hubs = dict(zip(G.nodes(), map(float, h.real))) authorities = dict(zip(G.nodes(), map(float, a.real))) return hubs, authorities
def aperiodic(self): G = self._as_digraph() return nx.is_aperiodic(G)
def power_iteration(G, max_iter=100, tol=1.0e-8, normalize=None, nstart=None, nstart_norm=None): ''' Calculates the steady state of graph using power method. In formal we use it when graph size is 2... Parameters ---------- G - networkx directed graph, the strongly connected component (subGraph) in our case max_iter - int, max iterations tol - float , the tolerance normalize - int, the number of nodes in the original (entire) graph- for normlizing the resulted eigenvector as per the proportion of the component from the entire (original) graph nstart - list of floats - the initial vector. nstart_norm - float, the weight [0,1] for normalizing the resulted eigenvector (for referring the risk proportion of the component from the entire (original) graph). *NOTE: normalize and nstart_norm cannot come together!! only one of them can be different from None! nstart and nstart_norm are not related to each other! Returns ------- results_dict - a dict of the (normalized) dominant eigenvector (the keys are G nodes names- basically integer) ''' import scipy #.sparse #import numpy as np startTime = datetime.now() n = nx.number_of_nodes(G) A = nx.to_scipy_sparse_matrix(G) if nstart is None: x = (scipy.ones((n, 1)) / n).T # initial guess else: #x=np.asarray(nstart_dict.values()).flatten() # IN MY CASE: is it the init of hubs or authorities?? x = np.asarray(nstart) # normalize starting vector s = 1.0 / x.sum() for k in x: x[k] *= s # power iteration on authority matrix i = 0 while True: xlast = x x = x * A # we multiple from left for extracting the matrix row x = x / x.max() # check convergence, l1 norm err = scipy.absolute(x - xlast).sum() if err < tol: break if i > max_iter: # in general- this method is used when there are only 2 nodes in the class # if the graph is aperiodic than the vector we got after max_iter is good eanough if nx.is_aperiodic(G): print '(salsa) power_iteration: (APERIODIC CLASS- ', n, ' nodes) failed to converge in %d iterations, continues with the last vector!!!' % ( i + 1) break else: #the class is periodic print '(salsa) power_iteration: (', n, ' nodes) PERIODIC CLASS!!!' raise NetworkXError( "(salsa) power_iteration: (PERIODIC CLASS) power iteration failed to converge in %d iterations." % (i + 1)) i += 1 results = np.asarray(x).flatten() results = results / results.sum() if normalize: norm_factor = float(G.number_of_nodes()) / normalize results = results * norm_factor elif nstart_norm != None: results = results * nstart_norm results_dict = dict(zip(G.nodes(), map(float, results))) #if n > 100: print '--- power_iteration: calc of class contains '+str(n)+' nodes, ('+str(float(n)/normalize)+'% of the main graph) took-'+str(datetime.now()-startTime); sys.stdout.flush() return results_dict
def test_is_aperiodic_cycle3(): G=nx.DiGraph() G.add_cycle([1,2,3,4]) G.add_cycle([3,4,5,6]) assert_false(nx.is_aperiodic(G))
def test_is_aperiodic_cycle2(): G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) nx.add_cycle(G, [3, 4, 5, 6, 7]) assert_true(nx.is_aperiodic(G))
def directed_laplacian_matrix(G, nodelist=None, weight='weight', walk_type=None, alpha=0.95): r"""Return the directed Laplacian matrix of G. The graph directed Laplacian is the matrix .. math:: L = I - (\Phi^{1/2} P \Phi^{-1/2} + \Phi^{-1/2} P^T \Phi^{1/2} ) / 2 where `I` is the identity matrix, `P` is the transition matrix of the graph, and `\Phi` a matrix with the Perron vector of `P` in the diagonal and zeros elsewhere. Depending on the value of walk_type, `P` can be the transition matrix induced by a random walk, a lazy random walk, or a random walk with teleportation (PageRank). Parameters ---------- G : DiGraph A NetworkX graph nodelist : list, optional The rows and columns are ordered according to the nodes in nodelist. If nodelist is None, then the ordering is produced by G.nodes(). weight : string or None, optional (default='weight') The edge data key used to compute each value in the matrix. If None, then each edge has weight 1. walk_type : string or None, optional (default=None) If None, `P` is selected depending on the properties of the graph. Otherwise is one of 'random', 'lazy', or 'pagerank' alpha : real (1 - alpha) is the teleportation probability used with pagerank Returns ------- L : NumPy array Normalized Laplacian of G. Raises ------ NetworkXError If NumPy cannot be imported NetworkXNotImplemnted If G is not a DiGraph Notes ----- Only implemented for DiGraphs See Also -------- laplacian_matrix References ---------- .. [1] Fan Chung (2005). Laplacians and the Cheeger inequality for directed graphs. Annals of Combinatorics, 9(1), 2005 """ import scipy as sp from scipy.sparse import identity, spdiags, linalg if walk_type is None: if nx.is_strongly_connected(G): if nx.is_aperiodic(G): walk_type = "random" else: walk_type = "lazy" else: walk_type = "pagerank" M = nx.to_scipy_sparse_matrix(G, nodelist=nodelist, weight=weight, dtype=float) n, m = M.shape if walk_type in ["random", "lazy"]: DI = spdiags(1.0/sp.array(M.sum(axis=1).flat), [0], n, n) if walk_type == "random": P = DI * M else: I = identity(n) P = (I + DI * M) / 2.0 elif walk_type == "pagerank": if not (0 < alpha < 1): raise nx.NetworkXError('alpha must be between 0 and 1') # this is using a dense representation M = M.todense() # add constant to dangling nodes' row dangling = sp.where(M.sum(axis=1) == 0) for d in dangling[0]: M[d] = 1.0 / n # normalize M = M / M.sum(axis=1) P = alpha * M + (1 - alpha) / n else: raise nx.NetworkXError("walk_type must be random, lazy, or pagerank") evals, evecs = linalg.eigs(P.T, k=1) v = evecs.flatten().real p = v / v.sum() sqrtp = sp.sqrt(p) Q = spdiags(sqrtp, [0], n, n) * P * spdiags(1.0/sqrtp, [0], n, n) I = sp.identity(len(G)) return I - (Q + Q.T) /2.0
def write_dag_info(G, report_file): report_file.write("===DAG_INFO===\n") report_file.write("Is DAG: {}\n".format(nx.is_directed_acyclic_graph(G))) report_file.write("Is aperiodic: {}\n".format(nx.is_aperiodic(G)))
def is_aperiodic(G): """Returns True if `G` is aperiodic. A directed graph is aperiodic if there is no integer k > 1 that divides the length of every cycle in the graph. Parameters ---------- G : NetworkX DiGraph A directed graph Returns ------- bool True if the graph is aperiodic False otherwise Raises ------ NetworkXError If `G` is not directed Examples -------- A graph consisting of one cycle, the length of which is 2. Therefore ``k = 2`` divides the length of every cycle in the graph and thus the graph is *not aperiodic*:: >>> DG = nx.DiGraph([(1, 2), (2, 1)]) >>> nx.is_aperiodic(DG) False A graph consisting of two cycles: one of length 2 and the other of length 3. The cycle lengths are coprime, so there is no single value of k where ``k > 1`` that divides each cycle length and therefore the graph is *aperiodic*:: >>> DG = nx.DiGraph([(1, 2), (2, 3), (3, 1), (1, 4), (4, 1)]) >>> nx.is_aperiodic(DG) True A graph consisting of two cycles: one of length 2 and the other of length 4. The lengths of the cycles share a common factor ``k = 2``, and therefore the graph is *not aperiodic*:: >>> DG = nx.DiGraph([(1, 2), (2, 1), (3, 4), (4, 5), (5, 6), (6, 3)]) >>> nx.is_aperiodic(DG) False An acyclic graph, therefore the graph is *not aperiodic*:: >>> DG = nx.DiGraph([(1, 2), (2, 3)]) >>> nx.is_aperiodic(DG) False Notes ----- This uses the method outlined in [1]_, which runs in $O(m)$ time given $m$ edges in `G`. Note that a graph is not aperiodic if it is acyclic as every integer trivial divides length 0 cycles. References ---------- .. [1] Jarvis, J. P.; Shier, D. R. (1996), "Graph-theoretic analysis of finite Markov chains," in Shier, D. R.; Wallenius, K. T., Applied Mathematical Modeling: A Multidisciplinary Approach, CRC Press. """ if not G.is_directed(): raise nx.NetworkXError( "is_aperiodic not defined for undirected graphs") s = arbitrary_element(G) levels = {s: 0} this_level = [s] g = 0 lev = 1 while this_level: next_level = [] for u in this_level: for v in G[u]: if v in levels: # Non-Tree Edge g = gcd(g, levels[u] - levels[v] + 1) else: # Tree Edge next_level.append(v) levels[v] = lev this_level = next_level lev += 1 if len(levels) == len(G): # All nodes in tree return g == 1 else: return g == 1 and nx.is_aperiodic(G.subgraph(set(G) - set(levels)))
def test_is_aperiodic_cycle(): G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) assert_false(nx.is_aperiodic(G))
def test_is_aperiodic_cycle3(): G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) nx.add_cycle(G, [3, 4, 5, 6]) assert_false(nx.is_aperiodic(G))
def __init__(self, num_states, rand=True, arm_count=0): self.num_states = num_states self.cumulative_reward = 0.0 self.pull_count = 0 self.rand = rand self.arm_count = arm_count if self.rand: # create ergodic transition matrix self.tran_matrix = np.zeros((num_states, num_states)) ergodic = False while ergodic == False: P = np.random.rand(num_states, num_states) P = preprocessing.normalize(P, norm='l1', axis=1, copy=True, return_norm=False) dic = {} for i in range(num_states): for j in range(num_states): dic[(i, j)] = P[i, j] T = pykov.Chain(dic) G = nx.DiGraph(list(T.keys())) if nx.is_strongly_connected(G) and nx.is_aperiodic(G): ergodic = True self.tran_matrix = P else: if self.arm_count == 0: self.tran_matrix = np.array([[0., 1.], [.01, .99]]) if self.arm_count == 1: self.tran_matrix = np.array([[.99, .01], [1., 0.]]) # find the steady state distribution mc = markovChain(self.tran_matrix) mc.computePi('linear') # We can also use 'power', 'krylov' or 'eigen' self.steady_state = np.asmatrix(mc.pi) # find ergodic constants P_tilde = np.zeros( (self.num_states, self.num_states)) # P_tilde as per Formula 2.1 in Page 65 for x in range(self.num_states): for y in range(self.num_states): P_tilde[x, y] = self.steady_state[0, y] * self.tran_matrix[ y, x] / self.steady_state[0, x] MP = np.dot(self.tran_matrix, P_tilde) eigenval, _ = np.linalg.eig(MP) self.eta = np.sort(eigenval)[-2] # Second largest eigenvalue self.eta = np.sqrt(self.eta) # sqrt for TV norm # Now we need to compute C using chi_0 square in Thm 2.7 # Here we don't have information about current state, # given a steady state distribution, chi_0 is maximized when current state is of the form (1,0,0,0,0,0) curr_state = np.zeros((1, self.num_states)) index = np.argmin(self.steady_state) curr_state[0, index] = 1.0 self.C = 0.25 * sum([(self.steady_state[0, i] - curr_state[0, i])**2 / self.steady_state[0, i] for i in range(self.num_states)]) self.C = np.sqrt(self.C) # sqrt for TV norm if self.rand: self.reward_type = np.random.randint(0, 3) self.set_reward_parameters() else: if self.arm_count == 0: self.rewards = np.array([0, 1]) elif self.arm_count == 1: self.rewards = np.array([.5, .5])
def test_is_aperiodic_selfloop(): G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) G.add_edge(1, 1) assert_true(nx.is_aperiodic(G))
def test_is_aperiodic_rary_tree(): G = nx.full_rary_tree(3, 27, create_using=nx.DiGraph()) assert not nx.is_aperiodic(G)
def test_is_aperiodic_rary_tree(): G = nx.full_rary_tree(3, 27, create_using=nx.DiGraph()) assert_false(nx.is_aperiodic(G))
def test_is_aperiodic_disconnected2(): G = nx.DiGraph() nx.add_cycle(G, [0, 1, 2]) G.add_edge(3, 3) assert not nx.is_aperiodic(G)
def test_is_aperiodic_disconnected2(): G = nx.DiGraph() nx.add_cycle(G, [0, 1, 2]) G.add_edge(3, 3) assert_false(nx.is_aperiodic(G))
def test_scipy_sparse_eigs(G, CN_name, self_link=False, seed_creation=False): eps = gm.epsilon print 'percentage of non-zero elements: '+str(float(np.count_nonzero(Transition_Matrix))/G.number_of_nodes()**2) print 'is strongly connected? '+str(nx.is_strongly_connected(G))+'\nis aperiodic? '+str(nx.is_aperiodic(G)) M = salsa.get_matrix(G, mat_type='hub', sparse=True) CN_index = G.nodes().index(CN_name) M = gm.convert_SL_and_CN_weights_to_val(M, val=eps, CN_idx=CN_index, stochastic_out=True) new_G = nx.DiGraph(M) print 'AFTER get matrix:\npercentage of non-zero elements: ' + str(float(M.getnnz())/G.number_of_nodes()**2) print 'is strongly connected? '+str(nx.is_strongly_connected(new_G))+'\nis aperiodic? '+str(nx.is_aperiodic(new_G)) print 'is stochastic? '+str(gm.check_if_stochastic_matrix(M.todense())) print M print M.shape[0] #M_pow = np.linalg.matrix_power(M.todense(), 111) #print M_pow e,ev=sp.sparse.linalg.eigen.arpack.eigs(M.copy().T, k=1,sigma=1, which='LM')#, maxiter=100000) h = ev/ev.sum() print e; print h; if (h.imag.sum() != 0.): print '##### COMPLEX VECTOR!!!! #####' print map(float,h.real) '''e1,ev1=sp.linalg.eig(M.todense(),left=True,right=False) m=e1.argsort()[-1] evMax1=np.array(ev1[:,m]).flatten() print '\n\tnp.linalg.eig(left)\n' + str(e1[m]) + '\n' + str(evMax1) ''' return
def test_is_aperiodic_cycle3(): G = nx.DiGraph() nx.add_cycle(G, [1, 2, 3, 4]) nx.add_cycle(G, [3, 4, 5, 6]) assert not nx.is_aperiodic(G)
def test_is_aperiodic_disconnected2(): G = nx.DiGraph() G.add_cycle([0,1,2]) G.add_edge(3,3) assert_false(nx.is_aperiodic(G))
def test_is_aperiodic_bipartite(): # Bipartite graph G = nx.DiGraph(nx.davis_southern_women_graph()) assert not nx.is_aperiodic(G)
def salsa_sparse(G,CN_name='CN',normalized=True, debug_mode=False): """Return HITS hubs and authorities values for nodes. The HITS algorithm computes two numbers for a node. Authorities estimates the node value based on the incoming links. Hubs estimates the node value based on outgoing links. Parameters ----------- G : graph A NetworkX graph normalized : bool (default=True) Normalize results by the sum of all of the values. Returns ------- (hubs,authorities) : two-tuple of dictionaries Two dictionaries keyed by node containing the hub and authority values. Examples -------- >>> G=nx.path_graph(4) >>> h,a=nx.hits(G) Notes ----- The eigenvector calculation uses NumPy's interface to LAPACK. The HITS algorithm was designed for directed graphs but this algorithm does not check if the input graph is directed and will execute on undirected graphs. References ---------- .. [1] A. Langville and C. Meyer, "A survey of eigenvector methods of web information retrieval." http://citeseer.ist.psu.edu/713792.html .. [2] Jon Kleinberg, Authoritative sources in a hyperlinked environment Journal of the ACM 46 (5): 604-32, 1999. doi:10.1145/324133.324140. http://www.cs.cornell.edu/home/kleinber/auth.pdf. """ print '\n\t~~~~~~ salsa_sparse (G, CN_name='+str(CN_name)+', normalized='+str(normalized)+', debug_mode='+str(debug_mode)+') ~~~~~~\n' try: #import numpy as np import scipy as sp import sys except ImportError: raise ImportError(\ "salsa_sparse() requires SciPy: http://scipy.org/") if len(G) == 0: return {},{} print '--- salsa_sparse: start time- ' + str(datetime.now()); sys.stdout.flush() startTime = datetime.now() #np.set_printoptions(precision=3) # For printing numpy objects- prints 3 decimal after the point. print '--- salsa_sparse: hub- percentage of non-zero elements: '+str(float(nx.to_scipy_sparse_matrix(G).getnnz())/G.number_of_nodes()**2); sys.stdout.flush() H = get_matrix(G,mat_type='hub',sparse=True) print '--- salsa_sparse: get_matrix (hub) took: '+str(datetime.now()-startTime); tmpTime = datetime.now(); sys.stdout.flush() print '--- salsa_sparse: hub- percentage of non-zero elements: '+str(float(H.getnnz())/G.number_of_nodes()**2); sys.stdout.flush() eps = gm.epsilon H = gm.convert_SL_and_CN_weights_to_val(H, val=eps, CN_idx=G.nodes().index(CN_name), stochastic_out=True) print '\n--- salsa_sparse: convert_SL_and_CN_weights_to_val took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now(); sys.stdout.flush() print '--- salsa_sparse: hub- percentage of non-zero elements: '+str(float(H.getnnz())/G.number_of_nodes()**2); sys.stdout.flush() if debug_mode: new_G_h = nx.DiGraph(H) print '\n--- salsa_sparse: hub- is new graph stochastic? ' + str(gm.check_if_stochastic_matrix(nx.to_numpy_matrix(new_G_h))); sys.stdout.flush() print '--- salsa_sparse: hub- is new graph strongly connected? ' + str(nx.is_strongly_connected(new_G_h)); sys.stdout.flush() print '--- salsa_sparse: hub- is new graph aperiodic? ' + str(nx.is_aperiodic(new_G_h)); sys.stdout.flush() new_G_h.clear() print '--- salsa_sparse: debug steps (hub) took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now(); sys.stdout.flush() #H = gm.convert_all_matrix_zeros_to_val(H_sparse, val=eps, stochastic_out=True) e,h = sp.sparse.linalg.eigen.arpack.eigs(H.T, k=1, sigma=1, which='LM') print '\n--- salsa_sparse: calculating hub eigs took: ' + str(datetime.now()-tmpTime); sys.stdout.flush() tmpTime = datetime.now() A = get_matrix(G,mat_type='authority',sparse=True) print '--- salsa_sparse: get_matrix (authority) took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now(); sys.stdout.flush() print '--- salsa_sparse: authority- percentage of non-zero elements: '+str(float(A.getnnz())/G.number_of_nodes()**2); sys.stdout.flush() A = gm.convert_SL_and_CN_weights_to_val(A, val=eps, CN_idx=G.nodes().index(CN_name), stochastic_out=True) print '\n--- salsa_sparse: convert_SL_and_CN_weights_to_val took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now(); sys.stdout.flush() print '--- salsa_sparse: authority- percentage of non-zero elements: '+str(float(A.getnnz())/G.number_of_nodes()**2); sys.stdout.flush() if debug_mode: new_G_a = nx.DiGraph(A) print '\n--- salsa_sparse: hub- is new graph stochastic? ' + str(gm.check_if_stochastic_matrix(nx.to_numpy_matrix(new_G_a))); sys.stdout.flush() print '--- salsa_sparse: authority- is new graph strongly connected? ' + str(nx.is_strongly_connected(new_G_a)); sys.stdout.flush() print '--- salsa_sparse: authority- is new graph aperiodic? ' + str(nx.is_aperiodic(new_G_a)); sys.stdout.flush() new_G_a.clear() print '--- salsa_sparse: debug steps (authority) took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now(); sys.stdout.flush() #A = gm.convert_all_matrix_zeros_to_val(A_sparse, val=eps, stochastic_out=True) #print '--- salsa_numpy: convert_all_matrix_zeros_to_eps took: '+str(datetime.now()-tmpTime); tmpTime = datetime.now() e,a = sp.sparse.linalg.eigen.arpack.eigs(A.T, k=1, sigma=1, which='LM') print '\n--- salsa_sparse: calculating hub eigs took: ' + str(datetime.now()-tmpTime); sys.stdout.flush() if normalized: h = h/h.sum() a = a/a.sum() else: h = h/h.max() a = a/a.max() if (h.imag.sum() != 0. or a.imag.sum() != 0. ): print '##### COMPLEX VECTOR!!!! returning the real part only!!! #####'; sys.stdout.flush() hubs=dict(zip(G.nodes(),map(float,h.real))) authorities=dict(zip(G.nodes(),map(float,a.real))) return hubs,authorities
def test_is_aperiodic_cycle(): G=nx.DiGraph() G.add_cycle([1,2,3,4]) assert_false(nx.is_aperiodic(G))
def test_is_aperiodic_cycle4(): G = nx.DiGraph() G.add_cycle([1,2,3,4]) G.add_edge(1,3) assert_true(nx.is_aperiodic(G))
def directed_laplacian_matrix(G, nodelist=None, weight='weight', walk_type=None, alpha=0.95): r"""Return the directed Laplacian matrix of G. The graph directed Laplacian is the matrix .. math:: L = I - (\Phi^{1/2} P \Phi^{-1/2} + \Phi^{-1/2} P^T \Phi^{1/2} ) / 2 where `I` is the identity matrix, `P` is the transition matrix of the graph, and `\Phi` a matrix with the Perron vector of `P` in the diagonal and zeros elsewhere. Depending on the value of walk_type, `P` can be the transition matrix induced by a random walk, a lazy random walk, or a random walk with teleportation (PageRank). Parameters ---------- G : DiGraph A NetworkX graph nodelist : list, optional The rows and columns are ordered according to the nodes in nodelist. If nodelist is None, then the ordering is produced by G.nodes(). weight : string or None, optional (default='weight') The edge data key used to compute each value in the matrix. If None, then each edge has weight 1. walk_type : string or None, optional (default=None) If None, `P` is selected depending on the properties of the graph. Otherwise is one of 'random', 'lazy', or 'pagerank' alpha : real (1 - alpha) is the teleportation probability used with pagerank Returns ------- L : NumPy array Normalized Laplacian of G. Raises ------ NetworkXError If NumPy cannot be imported NetworkXNotImplemnted If G is not a DiGraph Notes ----- Only implemented for DiGraphs See Also -------- laplacian_matrix References ---------- .. [1] Fan Chung (2005). Laplacians and the Cheeger inequality for directed graphs. Annals of Combinatorics, 9(1), 2005 """ import scipy as sp from scipy.sparse import identity, spdiags, linalg if walk_type is None: if nx.is_strongly_connected(G): if nx.is_aperiodic(G): walk_type = "random" else: walk_type = "lazy" else: walk_type = "pagerank" M = nx.to_scipy_sparse_matrix(G, nodelist=nodelist, weight=weight, dtype=float) n, m = M.shape if walk_type in ["random", "lazy"]: DI = spdiags(1.0 / sp.array(M.sum(axis=1).flat), [0], n, n) if walk_type == "random": P = DI * M else: I = identity(n) P = (I + DI * M) / 2.0 elif walk_type == "pagerank": if not (0 < alpha < 1): raise nx.NetworkXError('alpha must be between 0 and 1') # this is using a dense representation M = M.todense() # add constant to dangling nodes' row dangling = sp.where(M.sum(axis=1) == 0) for d in dangling[0]: M[d] = 1.0 / n # normalize M = M / M.sum(axis=1) P = alpha * M + (1 - alpha) / n else: raise nx.NetworkXError("walk_type must be random, lazy, or pagerank") evals, evecs = linalg.eigs(P.T, k=1) v = evecs.flatten().real p = v / v.sum() sqrtp = sp.sqrt(p) Q = spdiags(sqrtp, [0], n, n) * P * spdiags(1.0 / sqrtp, [0], n, n) I = sp.identity(len(G)) return I - (Q + Q.T) / 2.0
def test_eig_methods(): eps = gm.epsilon # ERGODIC initial matrix: print '/t~~~ 11_nodes_with_one_CN_and_SL ~~~' Transition_Matrix_ergodic,nstart=create_transition_matrix_for_testing(graph_type='11_nodes_with_one_CN_and_SL', self_link=True, seed_creation=False) G=nx.DiGraph(Transition_Matrix_ergodic) print nx.strongly_connected_components(G); print nx.is_strongly_connected(G); print nx.is_aperiodic(G) M=salsa.get_matrix(G, mat_type='hub', sparse=True) G_ = nx.DiGraph(M) print nx.strongly_connected_components(G_); print nx.is_strongly_connected(G_); print nx.is_aperiodic(G_) print 'num of non-zero elements: ' + str(M.getnnz()) print '11 nodes with one CN and SL after get_matrix , before the eps filling: is stochastic- '+str(gm.check_if_stochastic_matrix(M.todense())) #L = gm.convert_all_matrix_zeros_to_val(M, val=eps, stochastic_out=True) #is_sparse=True, L=M.todense() #print 'num of non-zero elements after filling: ' + str(np.count_nonzero(L)) Lden = L.copy().T #print 'all Matrix elements are positiv: ' + str((Lden > 0).all()) e1,ev1=sp.linalg.eig(L,left=True,right=False) m=e1.argsort()[-1] evMax1=np.array(ev1[:,m]).flatten() #print '\n\tnp.linalg.eig(left)\n' + str(e1[m]) + '\n' + str(evMax1) print '\n\tsp.linalg.eig(Lden,left=True,right=False)\n' + str(round(e1[m],3)) + '\n' + str(gm.l1_norm_vector(evMax1).round(3)) #print '\nall eigval:\n'+str(e1.round(3))+'\n\nall eigvec:\n'+str(ev1.round(3)) # NOT ERGODIC initial matrix (with root CN but no Self Links): print '\n\t~~~ 11_nodes_with_one_CN ~~~~' Transition_Matrix_CN_no_SL,nstart2=create_transition_matrix_for_testing(graph_type='11_nodes_with_one_CN', self_link=False, seed_creation=False) G2=nx.DiGraph(Transition_Matrix_CN_no_SL) print nx.strongly_connected_components(G2); print nx.is_strongly_connected(G2); print nx.is_aperiodic(G2) M2=salsa.get_matrix(G2, mat_type='hub', sparse=True) G2_ = nx.DiGraph(M2) print nx.strongly_connected_components(G2_); print nx.is_strongly_connected(G2_); print nx.is_aperiodic(G2_) print 'num of non-zero elements: ' + str(M2.getnnz()) print '11 nodes with one CN after get_matrix , before the eps filling: is stochastic- '+str(gm.check_if_stochastic_matrix(M2.todense())) #print '/n11 nodes with one CN after get , before the eps filling: \n'+str(M2.todense()) #L2 = gm.convert_all_matrix_zeros_to_val(M2, val=eps, stochastic_out=True) #is_sparse=True, #print 'num of non-zero elements after filling: ' + str(np.count_nonzero(L2)) L2 = M2.todense() Lden2 = L2.copy().T e_np,ev_np=np.linalg.eig(Lden2) m=e_np.argsort()[-1] evMax_np=np.array(ev_np[:,m]).flatten() #print '\n\tnp.linalg.eig(left)\n' + str(e_np[m]) + '\n' + str(evMax_np) print '\n\tnp.linalg.eig(left)\n' + str(round(e_np[m],3)) + '\n' + str(gm.l1_norm_vector(evMax_np).round(3)) ''' # NSTART: e_eigs,ev_eigs= eigs(M.copy().T, k=1, which='LM', v0=nstart_list, tol=0.001) #eigs(L.T, k=1, which='LM', v0=nstart_list, tol=0.0001) print '\n\teigs(M.T, k=1, which=LM)\n' + str(e_eigs.round(3)) + '\n' + str(ev_eigs.round(3)) ''' ''' # SPARSE: e,ev=sp.sparse.linalg.eigen.arpack.eigs(M.copy().T, k=1, which='LM')#left=True,right=False) m=e.argsort()[-1] evMax=np.array(ev[:,m]).flatten() print '\n\tsp.sparse.linalg.eigen.arpack.eigs(left, k=1, which=LM)\n' + str(round(e[m],3)) + '\n' + str(evMax.round(3)) ''' return