Skip to content

Commit

Permalink
Merge pull request #23 from Graphlet-AI/rjurney/unpin-get-nodes
Browse files Browse the repository at this point in the history
Upgrade versions on dependencies - NetworKit 10.X
  • Loading branch information
benedekrozemberczki committed Jul 1, 2023
2 parents e3f9f9f + 64b7ea5 commit ae585fa
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 104 deletions.
61 changes: 15 additions & 46 deletions littleballoffur/backend.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import random
import numpy as np
import networkx as nx
import networkit as nk
from typing import List, Tuple

import networkit as nk
import networkx as nx
import numpy as np

NKGraph = type(nk.graph.Graph())
NXGraph = nx.classes.graph.Graph
Expand All @@ -13,6 +13,7 @@ class NetworKitBackEnd(object):
"""
Binding the NetworKit backend to serve graph operations.
"""

def __init__(self):
pass

Expand All @@ -22,77 +23,66 @@ def get_number_of_nodes(self, graph: NKGraph) -> int:
"""
return graph.numberOfNodes()


def get_number_of_edges(self, graph: NKGraph) -> int:
"""
Given a graph return the number of edges.
"""
return graph.numberOfEdges()


def get_nodes(self, graph: NKGraph) -> List:
"""
Given a graph return the nodes.
"""
return graph.nodes()

return [node for node in self.get_node_iterator(graph)]

def get_edges(self, graph: NKGraph) -> List[Tuple]:
"""
Given a graph return the edges.
"""
return graph.edges()

return [edge for edge in self.get_edge_iterator(graph)]

def get_node_iterator(self, graph: NKGraph):
"""
Given a graph return the node iterator.
"""
return graph.iterNodes()


def get_edge_iterator(self, graph: NKGraph):
"""
Given a graph return the edge iterator.
"""
return graph.iterEdges()


def get_degree(self, graph: NKGraph, node: int) -> int:
"""
Given a graph and node return the degree.
"""
return graph.degree(node)


def get_subgraph(self, graph: NKGraph, nodes: List[int]) -> NKGraph:
"""
Given a graph and set of inducing nodes return a subgraph.
"""
return graph.subgraphFromNodes(nodes)

return nk.graphtools.subgraphFromNodes(graph, nodes)

def get_neighbors(self, graph: NKGraph, node: int) -> List[int]:
"""
Given a graph and node return the neighbors.
"""
return graph.neighbors(node)

return [node for node in graph.iterNeighbors(node)]

def get_random_neighbor(self, graph: NKGraph, node: int) -> int:
"""
Given a graph and node returns a random neighbor.
"""
return graph.randomNeighbor(node)

return nk.graphtools.randomNeighbor(graph, node)

def get_shortest_path(self, graph: NKGraph, source: int, target: int) -> List[int]:
"""
Given a graph, a source and target node pair get the shortes path
"""
return nk.distance.ReverseBFS(graph, source, True, False, target).run().getPath(target)


def get_pagerank(self, graph: NKGraph, alpha: float) -> np.array:
"""
Given a graph return the PageRank vector.
Expand All @@ -118,31 +108,26 @@ def graph_from_edgelist(self, edges: List) -> NKGraph:
new_graph.addEdge(edge[0], edge[1], addMissing=True)
return new_graph


def _check_networkit_graph(self, graph: NKGraph):
"""Chechking the input type."""
assert isinstance(graph, NKGraph), "This is not a NetworKit graph."


def _check_connectivity(self, graph: NKGraph):
"""Checking the connected nature of a single graph."""
connected = nk.components.ConnectedComponents(graph).run().numberOfComponents()
assert connected == 1, "Graph is not connected."


def _check_directedness(self, graph: NXGraph):
"""Checking the undirected nature of a single graph."""
directed = graph.isDirected()
assert directed == False, "Graph is directed."


def _check_indexing(self, graph: NKGraph):
"""Checking the consecutive numeric indexing."""
numeric_indices = [index for index in range(graph.numberOfNodes())]
node_indices = sorted([node for node in graph.nodes()])
node_indices = sorted([node for node in self.get_nodes(graph)])
assert numeric_indices == node_indices, "The node indexing is wrong."


def check_graph(self, graph: NKGraph):
"""Check the Little Ball of Fur assumptions about the graph."""
self._check_networkit_graph(graph)
Expand All @@ -154,93 +139,82 @@ class NetworkXBackEnd(object):
"""
Binding the NetworkX backend to serve graph operations.
"""

def __init__(self):
pass


def get_number_of_nodes(self, graph: NXGraph) -> int:
"""
Given a graph return the number of nodes.
"""
return graph.number_of_nodes()


def get_number_of_edges(self, graph: NXGraph) -> int:
"""
Given a graph return the number of edges.
"""
return graph.number_of_edges()


def get_nodes(self, graph: NXGraph) -> List:
"""
Given a graph return the nodes.
"""
return [node for node in graph.nodes()]

return [node for node in self.get_node_iterator(graph)]

def get_edges(self, graph: NXGraph) -> List[Tuple]:
"""
Given a graph return the edges.
"""
return [edge for edge in graph.edges()]


def get_node_iterator(self, graph: NXGraph):
"""
Given a graph return the node iterator.
"""
return graph.nodes()


def get_edge_iterator(self, graph: NXGraph):
"""
Given a graph return the edge iterator.
"""
return graph.edges()


def get_degree(self, graph: NXGraph, node: int) -> int:
"""
Given a graph and node return the degree.
"""
return graph.degree[node]


def get_subgraph(self, graph: NXGraph, nodes: List[int]) -> NXGraph:
"""
Given a graph and set of inducing nodes return a subgraph.
"""
return graph.subgraph(nodes)


def get_neighbors(self, graph: NXGraph, node: int) -> List[int]:
"""
Given a graph and node return the neighbors.
"""
return [node for node in graph.neighbors(node)]


def get_random_neighbor(self, graph: NXGraph, node: int) -> int:
"""
Given a graph and node returns a random neighbor.
"""
neighbors = self.get_neighbors(graph, node)
return random.choice(neighbors)


def get_shortest_path(self, graph: NXGraph, source: int, target: int) -> List[int]:
"""
Given a graph, a source and target node pair get the shortes path
"""
return nx.shortest_path(graph, source, target)


def get_pagerank(self, graph: NXGraph, alpha: float) -> np.array:
"""
Given a graph return the PageRank vector.
"""
pagerank = nx.pagerank_scipy(graph, alpha=alpha)
pagerank = nx.pagerank(graph, alpha=alpha)
pagerank = np.array([pagerank[node] for node in graph.nodes()])
pagerank = pagerank / pagerank.sum()
return pagerank
Expand All @@ -249,7 +223,7 @@ def is_weighted(self, graph: NXGraph) -> bool:
return nx.is_weighted(graph)

def get_edge_weight(self, graph: NXGraph, u: int, v: int) -> float:
return graph.get_edge_data(u, v)['weight']
return graph.get_edge_data(u, v)["weight"]

def graph_from_edgelist(self, edges: List) -> NXGraph:
"""
Expand All @@ -258,33 +232,28 @@ def graph_from_edgelist(self, edges: List) -> NXGraph:
graph = nx.from_edgelist(edges)
return graph


def _check_networkx_graph(self, graph: NXGraph):
"""Chechking the input type."""
assert isinstance(graph, NXGraph), "This is not a NetworkX graph."


def _check_connectivity(self, graph: NXGraph):
"""Checking the connected nature of a single graph."""
connected = nx.is_connected(graph)
assert connected, "Graph is not connected."


def _check_directedness(self, graph: NXGraph):
"""Checking the undirected nature of a single graph."""
directed = nx.is_directed(graph)
assert directed == False, "Graph is directed."


def _check_indexing(self, graph: NXGraph):
"""Checking the consecutive numeric indexing."""
numeric_indices = [index for index in range(graph.number_of_nodes())]
node_indices = sorted([node for node in graph.nodes()])
assert numeric_indices == node_indices, "The node indexing is wrong."


def check_graph(self, graph: NXGraph):
"""Check the Little Ball of Fur assumptions about the graph."""
self._check_networkx_graph(graph)
self._check_directedness(graph)
self._check_indexing(graph)
self._check_indexing(graph)
31 changes: 15 additions & 16 deletions littleballoffur/sampler.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import random
import numpy as np
import networkx as nx
import networkit as nk
from typing import Union
from littleballoffur.backend import NetworKitBackEnd
from littleballoffur.backend import NetworkXBackEnd

import networkit as nk
import networkx as nx
import numpy as np

from littleballoffur.backend import NetworKitBackEnd, NetworkXBackEnd

NKGraph = type(nk.graph.Graph())
NXGraph = nx.classes.graph.Graph
Expand Down Expand Up @@ -40,19 +40,22 @@ def _deploy_backend(self, graph: Union[NKGraph, NXGraph]):

def _check_networkx_graph(self, graph):
"""Chechking the input type."""
assert isinstance(
graph, nx.classes.graph.Graph
), "This is not a NetworkX graph."
assert isinstance(graph, nx.classes.graph.Graph), "This is not a NetworkX graph."

def _check_directedness(self, graph):
"""Checking the undirected nature of a single graph."""
directed = nx.is_directed(graph)
assert directed == False, "Graph is directed."
assert directed is False, "Graph is directed."

def _check_indexing(self, graph):
"""Checking the consecutive numeric indexing."""
numeric_indices = [index for index in range(graph.number_of_nodes())]
node_indices = sorted([node for node in graph.nodes()])
if hasattr(self, "backend") and isinstance(self.backend, NetworKitBackEnd):
node_indices = sorted([node for node in self.backend.get_nodes(graph)])
elif hasattr(self, "backend") and isinstance(self.backend, NetworkXBackEnd):
node_indices = sorted([node for node in graph.nodes()])
else:
node_indices = sorted([node for node in graph.nodes()])
assert numeric_indices == node_indices, "The node indexing is wrong."

def _check_graph(self, graph: nx.classes.graph.Graph):
Expand All @@ -64,13 +67,9 @@ def _check_graph(self, graph: nx.classes.graph.Graph):
def _check_number_of_nodes(self, graph):
"""Checking the size of the graph - nodes."""
if self.number_of_nodes > self.backend.get_number_of_nodes(graph):
raise ValueError(
"The number of nodes is too large. Please see requirements."
)
raise ValueError("The number of nodes is too large. Please see requirements.")

def _check_number_of_edges(self, graph):
"""Checking the size of the graph -- edges."""
if self.number_of_edges > self.backend.get_number_of_edges(graph):
raise ValueError(
"The number of edges is too large. Please see requirements."
)
raise ValueError("The number of edges is too large. Please see requirements.")
28 changes: 15 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import os

from setuptools import find_packages, setup

on_rtd = os.environ.get("READTHEDOCS") == "True"

install_requires = ["numpy<1.23.0",
"networkx<2.7",
"decorator==4.4.2",
"cmake",
"Cython",
"tqdm",
"python-louvain",
"pandas<=1.3.5",
"six",
"scipy"]
install_requires = [
"cmake>=3.26",
"Cython>=0.29",
"decorator>=5.1",
"networkx>=3.1",
"numpy>=1.21",
"pandas<2.0",
"python-louvain>=0.16",
"six",
"scipy>=1.10.0",
"tqdm",
]

if not on_rtd:
install_requires.append("networkit==7.1")
install_requires.append("networkit>=10.1")

setup_requires = ["cython", "numpy", "pytest-runner"]

tests_require = ["pytest", "pytest-cov", "mock", "unittest"]



keywords = [
"community",
"detection",
Expand All @@ -42,7 +44,7 @@

setup(
name="littleballoffur",
version="2.2.0",
version="2.3.0",
license="MIT",
description="A general purpose library for subsampling graphs.",
author="Benedek Rozemberczki",
Expand Down
Loading

0 comments on commit ae585fa

Please sign in to comment.