diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 0000000..6921003 --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: ae5712abed9b5413629774078a318328 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle new file mode 100644 index 0000000..8c77f04 Binary files /dev/null and b/.doctrees/environment.pickle differ diff --git a/.doctrees/index.doctree b/.doctrees/index.doctree new file mode 100644 index 0000000..035b008 Binary files /dev/null and b/.doctrees/index.doctree differ diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 0000000..f01d288 --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,80 @@ + + + +
+ + +
+import itertools
+import numpy as np
+import networkx as nx
+
+
+
+[docs]
+def find_sap(graph, start, target, path=None):
+
+ """
+ Finds all self-avoiding paths (SAPs) in a given graph from a start node to a target node.
+
+ A self-avoiding path is a path that does not revisit any node.
+
+ Parameters
+ ----------
+ graph : NetworkX graph
+ The input graph where SAPs will be found.
+ start : str or int
+ The node where the search for SAPs starts.
+ target : str or int
+ The node where the search for SAPs ends.
+ path : list, optional
+ Internal parameter used to keep track of the current path during the search.
+
+ Yields
+ ------
+ list
+ A self-avoiding path from the start node to the target node.
+
+ Examples
+ --------
+ >>> import networkx as nx
+ >>> G = nx.Graph()
+ >>> edges = [('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'F'), ('E', 'F')]
+ >>> G.add_edges_from(edges)
+ >>> start_node = 'A'
+ >>> target_node = 'F'
+ >>> all_saps = list(find_sap(G, start_node, target_node))
+ >>> for path in all_saps:
+ >>> print("->".join(path))
+ """
+
+ if path is None:
+ path = []
+
+ path.append(start)
+
+ if start == target:
+ yield path[:]
+ else:
+ for neighbor in graph.neighbors(start):
+ if neighbor not in path:
+ yield from find_sap(graph, neighbor, target, path)
+
+ path.pop()
+
+
+
+
+[docs]
+def is_hamiltonian_path(G, path):
+ '''
+ Check if a given path is a Hamiltonian path in a graph.
+
+ Parameters:
+ -----------
+ G : networkx.Graph, networkx.DiGraph)
+ The input graph.
+ path : list of str or int
+ list of nodes in the path.
+
+ Returns:
+ -----------
+ bool :
+ True if the path is a Hamiltonian path, otherwise False
+
+ '''
+ return all(G.has_edge(path[i], path[i + 1]) for i in range(len(path) - 1))
+
+
+
+
+[docs]
+def find_hamiltonian_path(G):
+ '''
+ find the Hamiltonian path in given graph.
+
+ Parameters
+ -----------
+ G: nx.Graph or nx.DiGraph
+ input graph.
+
+ Returns
+ value : list of nodes in Hamiltonian path if exists, otherwise None.
+
+ '''
+ nodes = list(G.nodes())
+ for perm in itertools.permutations(nodes):
+ if is_hamiltonian_path(G, perm):
+ return perm
+ return None
+
+
+
+
+[docs]
+def check_connectivity(G):
+ '''
+ Check if the graph is connected.
+
+ Parameters
+ --------------
+ G : networkx.Graph, networkx.DiGraph
+ The input graph.
+
+ Returns
+ ------------
+
+ connectivity: (str)
+ for directed graphs, it returns
+ - "weakly connected"
+ - "strongly connected"
+ - "disconnected".
+ for undirected graphs,
+ - "connected"
+ - "disconnected".
+ '''
+
+ is_directed = isinstance(G, nx.DiGraph)
+
+ if is_directed:
+ if nx.is_weakly_connected(G):
+ return "weakly connected"
+ elif nx.is_strongly_connected(G):
+ return "strongly connected"
+ else:
+ return "disconnected"
+ else:
+ if nx.is_connected(G):
+ return "connected"
+ else:
+ return "disconnected"
+
+
+
+[docs]
+def graph_info(G, quick=True):
+ """
+ Generate various graph information.
+
+ Parameters
+ -------------
+ G : (networkx.Graph, networkx.DiGraph)
+ The input graph for which the information is to be generated.
+
+
+ """
+ is_directed = isinstance(G, nx.DiGraph)
+
+ # number_of_triangles = #TODO
+
+ connectivity = check_connectivity(G)
+
+ if not quick:
+ if connectivity == "strongly connected" or connectivity == "connected":
+ diameter = nx.diameter(G)
+ else:
+ diameter = -1
+
+ print("Graph information")
+ print(f"{'Directed':40s}: {str(is_directed):>20s}")
+ print(f"{'Number of nodes':40s}: {len(G.nodes()):20d}")
+ print(f"{'Number of edges':40s}: {len(G.edges()):20d}")
+ print(f"{'Average degree':40s}: {sum(dict(G.degree).values()) / len(G.nodes):20.4f}")
+ print(f"{'Connectivity':40s}: {connectivity:>20s}")
+ if not quick:
+ print(f"{'Diameter':40s}: {diameter:20d}")
+ print(f"{'Average clustering coefficient':40s}: {nx.average_clustering(G):20.6f}")
+
+
+ # return {
+ # "Directed": is_directed,
+ # "Number of nodes": len(G.nodes()),
+ # "Number of edges": len(G.edges()),
+ # "average_degree": sum(dict(G.degree).values()) / len(G.nodes),
+ # "diameter": diameter,
+ # "average clustering coefficient": nx.average_clustering(G),
+
+ # }
+
+
+[docs]
+def longest_shortest_path(G):
+ """
+ Calculate the longest shortest path (diameter) in a given graph.
+
+ Parameters
+ -------------
+ G (networkx.Graph or networkx.DiGraph):
+ The input graph, which can be directed or undirected.
+ The graph should be connected, otherwise the diameter will not be defined.
+
+ Returns:
+ value : int, float
+ The longest shortest path (diameter) in the graph.
+ If the graph is empty, returns 0.
+ If the graph is not connected, returns float('inf').
+ """
+ path_lengths = dict(nx.all_pairs_shortest_path_length(G))
+ diameter = max(max(lengths.values()) for lengths in path_lengths.values())
+
+ return diameter
+
+
+
+
+[docs]
+def average_degree(G):
+ """
+ Calculate the average degree of a graph.
+
+ Parameters
+ -------------
+ G (networkx.Graph or networkx.DiGraph):
+ The input graph, which can be directed or undirected.
+
+ Returns:
+ vlaue: float
+ The average degree of the graph.
+ """
+
+ degrees = [d for n, d in G.degree()]
+ average_degree = sum(degrees) / len(degrees)
+ return average_degree
+
+
+import itertools
+import numpy as np
+import networkx as nx
+import matplotlib.pyplot as plt
+
+
+
+
+[docs]
+def plot_graph(G, **kwargs):
+ """
+ Plots a NetworkX graph with customizable options.
+
+ Parameters
+ ----------
+ G : NetworkX graph
+ A NetworkX graph object (e.g., nx.Graph, nx.DiGraph).
+ **kwargs : keyword arguments
+ Additional keyword arguments to customize the plot. These can include:
+
+ node_color : str or list, optional
+ Color of the nodes (can be a single color or a list of colors).
+ node_size : int or list, optional
+ Size of the nodes (single value or list of sizes).
+ edge_color : str or list, optional
+ Color of the edges (can be a single color or a list of colors).
+ width : float, optional
+ Width of the edges.
+ with_labels : bool, optional
+ Whether to draw node labels or not.
+ font_size : int, optional
+ Size of the font for node labels.
+ font_color : str, optional
+ Color of the font for node labels.
+ title : str, optional
+ Title of the plot.
+ seed : int, optional
+ Seed for the random layout algorithm.
+ figsize : tuple, optional
+ Size of the figure.
+
+ """
+
+ # Extracting optional arguments
+ node_color = kwargs.get("node_color", "lightblue")
+ node_size = kwargs.get("node_size", 300)
+ edge_color = kwargs.get("edge_color", "black")
+ width = kwargs.get("width", 1.0)
+ with_labels = kwargs.get("with_labels", True)
+ font_size = kwargs.get("font_size", 12)
+ font_color = kwargs.get("font_color", "black")
+ title = kwargs.get("title", None)
+ seed = kwargs.get("seed", None)
+ edge_labels = kwargs.get("edge_labels", None)
+ figsize = kwargs.get("figsize", (4, 4))
+
+ if "figsize" in kwargs:
+ plt.figure(figsize=figsize)
+ plt.axis("off")
+
+ if seed is not None:
+ np.random.seed(seed) # Set the random seed for reproducibility
+
+ # Position nodes using a layout algorithm
+ pos = nx.spring_layout(
+ G, seed=seed
+ ) # You can choose other layouts like nx.circular_layout(G) or nx.kamada_kaway_layout(G)
+
+ # Draw the network
+ nx.draw(
+ G,
+ pos,
+ node_color=node_color,
+ node_size=node_size,
+ edge_color=edge_color,
+ width=width,
+ with_labels=with_labels,
+ font_size=font_size,
+ font_color=font_color,
+ )
+
+ if edge_labels is not None:
+ nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
+
+ # Set the plot title
+ if title is not None:
+ plt.title(title)
+
+
+ # Show the plot
+ # plt.show()
+
+import os
+import gzip
+import numpy as np
+import networkx as nx
+
+
+
+[docs]
+def get_adjacency_list(G):
+ """
+ Generate an adjacency list representation of a given graph.
+
+ Parameters
+ -------------
+ G (networkx.Graph, networkx.DiGraph):
+ The input graph for which the adjacency list is to be generated.
+
+ Returns:
+ value: dict
+ A dictionary where each key is a node in the graph and the corresponding value is a list of neighboring nodes.
+ """
+ return {n: list(neighbors) for n, neighbors in G.adj.items()}
+
+
+
+
+[docs]
+def load_internet_graph():
+ '''
+ Load the P2P-Gnutella04 graph from the Stanford Network Analysis Project (SNAP).
+
+ References
+ - https://snap.stanford.edu/data/#communities
+ '''
+
+ path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ path = os.path.join(path, 'netsci/datasets')
+
+ file_path = os.path.join(path, 'p2p-Gnutella04.txt.gz')
+ os.system(f"gunzip -k {file_path}")
+ with gzip.open(file_path, 'rt') as f:
+ G = nx.read_adjlist(file_path)
+
+ os.remove(file_path[:-3])
+ return G
+
+
+
+
+[docs]
+def load_sample_graph(name):
+ """
+ Load a graph and return it as a NetworkX graph.
+
+ Parameters
+ --------------
+ name (str):
+ The name of the graph including:
+ - 'internet'
+
+ Returns
+ -----------
+ value: networkx.Graph
+ The loaded graph.
+ """
+
+ path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ path = os.path.join(path, 'netsci/datasets')
+ # print(path)
+
+ if name == 'internet':
+ return load_internet_graph()
+
+
+
' + + '' + + _("Hide Search Matches") + + "
" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/genindex.html b/genindex.html new file mode 100644 index 0000000..8a6181a --- /dev/null +++ b/genindex.html @@ -0,0 +1,216 @@ + + + + + + ++ |
+ |
+ | + |
+ | + |
+ |
+ | + |
|
+
+ | + |
+ |
Barabási, A.L., 2013. Network science. Philosophical Transactions of the Royal Society A: Mathematical, Physical and Engineering Sciences, 371(1987), p.20120375.
using on Colab (Recommended)
++++
+- +
Go to examples
- +
Open a notebook and click on “open on colab”
- +
Uncomment the cell with pip install command to install the netsci package.
using on local machines
pip3 install -e .
+# or
+pip install "git+https://github.com/Ziaeemehr/netsci.git"
+
Finds all self-avoiding paths (SAPs) in a given graph from a start node to a target node.
+A self-avoiding path is a path that does not revisit any node.
+The input graph where SAPs will be found.
+The node where the search for SAPs starts.
+The node where the search for SAPs ends.
+Internal parameter used to keep track of the current path during the search.
+A self-avoiding path from the start node to the target node.
+Examples
+>>> import networkx as nx
+>>> G = nx.Graph()
+>>> edges = [('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'F'), ('E', 'F')]
+>>> G.add_edges_from(edges)
+>>> start_node = 'A'
+>>> target_node = 'F'
+>>> all_saps = list(find_sap(G, start_node, target_node))
+>>> for path in all_saps:
+>>> print("->".join(path))
+
find the Hamiltonian path in given graph.
+input graph.
+Check if the graph is connected.
+The input graph.
+for directed graphs, it returns +- “weakly connected” +- “strongly connected” +- “disconnected”. +for undirected graphs, +- “connected” +- “disconnected”.
+Generate various graph information.
+The input graph for which the information is to be generated.
+Calculate the longest shortest path (diameter) in a given graph.
+The input graph, which can be directed or undirected. +The graph should be connected, otherwise the diameter will not be defined.
+The longest shortest path (diameter) in the graph. +If the graph is empty, returns 0. +If the graph is not connected, returns float(‘inf’).
+Generate an adjacency list representation of a given graph.
+The input graph for which the adjacency list is to be generated.
+A dictionary where each key is a node in the graph and the corresponding value is a list of neighboring nodes.
+Load the P2P-Gnutella04 graph from the Stanford Network Analysis Project (SNAP).
+References +- https://snap.stanford.edu/data/#communities
+Plots a NetworkX graph with customizable options.
+A NetworkX graph object (e.g., nx.Graph, nx.DiGraph).
+Additional keyword arguments to customize the plot. These can include:
+Color of the nodes (can be a single color or a list of colors).
+Size of the nodes (single value or list of sizes).
+Color of the edges (can be a single color or a list of colors).
+Width of the edges.
+Whether to draw node labels or not.
+Size of the font for node labels.
+Color of the font for node labels.
+Title of the plot.
+Seed for the random layout algorithm.
+Size of the figure.
++ n | ||
+ |
+ netsci | + |
+ |
+ netsci.analysis | + |
+ |
+ netsci.plot | + |
+ |
+ netsci.utils | + |
+ Searching for multiple words only shows matches that contain + all words. +
+ + + + + + + + + +