Skip to content

Commit

Permalink
Implement Backend#get_edge_count
Browse files Browse the repository at this point in the history
  • Loading branch information
j6k4m8 committed Apr 17, 2024
1 parent 255098c commit 41657e1
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 29 deletions.
39 changes: 29 additions & 10 deletions grand/backends/_dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,13 @@ def all_nodes_as_iterable(self, include_metadata: bool = False):
if self._node_df is not None:
return [
(
node_id,
row.to_dict(),
(
node_id,
row.to_dict(),
)
if include_metadata
else node_id
)
if include_metadata
else node_id
for node_id, row in self._node_df.iterrows()
]

Expand Down Expand Up @@ -355,9 +357,11 @@ def get_node_neighbors(self, u: Hashable, include_metadata: bool = False):
else:
return iter(
[
row[self._edge_df_source_column]
if row[self._edge_df_source_column] != u
else row[self._edge_df_target_column]
(
row[self._edge_df_source_column]
if row[self._edge_df_source_column] != u
else row[self._edge_df_target_column]
)
for _, row in self._edge_df[
(self._edge_df[self._edge_df_source_column] == u)
| (self._edge_df[self._edge_df_target_column] == u)
Expand Down Expand Up @@ -430,9 +434,11 @@ def get_node_predecessors(self, u: Hashable, include_metadata: bool = False):
else:
return iter(
[
row[self._edge_df_source_column]
if row[self._edge_df_target_column] != u
else row[self._edge_df_target_column]
(
row[self._edge_df_source_column]
if row[self._edge_df_target_column] != u
else row[self._edge_df_target_column]
)
for _, row in self._edge_df[
(self._edge_df[self._edge_df_target_column] == u)
| (self._edge_df[self._edge_df_source_column] == u)
Expand Down Expand Up @@ -460,6 +466,19 @@ def get_node_count(self) -> int:
)
)

def get_edge_count(self) -> int:
"""
Get an integer count of the number of edges in this graph.
Arguments:
None
Returns:
int: The count of edges
"""
return len(self._edge_df)

def ingest_from_edgelist_dataframe(
self, edgelist: pd.DataFrame, source_column: str, target_column: str
) -> dict:
Expand Down
33 changes: 26 additions & 7 deletions grand/backends/_dynamodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,13 @@ def all_nodes_as_iterable(self, include_metadata: bool = False) -> Collection:
"""
return [
(
node[self._primary_key],
{k: v for k, v in node.items() if k not in [self._primary_key]},
(
node[self._primary_key],
{k: v for k, v in node.items() if k not in [self._primary_key]},
)
if include_metadata
else node[self._primary_key]
)
if include_metadata
else node[self._primary_key]
for node in self._scan_table(self._node_table)
]

Expand Down Expand Up @@ -264,9 +266,11 @@ def all_edges_as_iterable(self, include_metadata: bool = False) -> Collection:
"""
return [
(edge[self._edge_source_key], edge[self._edge_target_key], edge)
if include_metadata
else (edge[self._edge_source_key], edge[self._edge_target_key])
(
(edge[self._edge_source_key], edge[self._edge_target_key], edge)
if include_metadata
else (edge[self._edge_source_key], edge[self._edge_target_key])
)
for edge in self._scan_table(self._edge_table)
]

Expand Down Expand Up @@ -435,6 +439,21 @@ def get_node_count(self) -> int:
"ItemCount"
]

def get_edge_count(self) -> int:
"""
Get an integer count of the number of edges in this graph.
Arguments:
None
Returns:
int: The count of edges
"""
return self._client.describe_table(TableName=self._edge_table_name)["Table"][
"ItemCount"
]

# Ingesting

def ingest_from_edgelist_dataframe(
Expand Down
13 changes: 13 additions & 0 deletions grand/backends/_gremlin.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,5 +314,18 @@ def get_node_count(self) -> int:
"""
return self._g.V().count().toList()[0]

def get_edge_count(self) -> int:
"""
Get an integer count of the number of edges in this graph.
Arguments:
None
Returns:
int: The count of edges
"""
return self._g.E().count().toList()[0]

def teardown(self) -> None:
self._g.V().drop().toList()
13 changes: 13 additions & 0 deletions grand/backends/_igraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,16 @@ def get_node_count(self) -> int:
"""
return self._ig.vcount()

def get_edge_count(self) -> int:
"""
Get an integer count of the number of edges in this graph.
Arguments:
None
Returns:
int: The count of edges
"""
return self._ig.ecount()
17 changes: 15 additions & 2 deletions grand/backends/_networkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def get_node_predecessors(
[self._names.get_name(i) for i in self._nk_graph.iterInNeighbors(my_id)]
)

def get_node_count(self) -> Iterable:
def get_node_count(self) -> int:
"""
Get an integer count of the number of nodes in this graph.
Expand All @@ -292,4 +292,17 @@ def get_node_count(self) -> Iterable:
int: The count of nodes
"""
return len([i for i in self.all_nodes_as_iterable()])
return self._nk_graph.numberOfNodes()

def get_edge_count(self) -> int:
"""
Get an integer count of the number of edges in this graph.
Arguments:
None
Returns:
int: The count of edges
"""
return self._nk_graph.numberOfEdges()
16 changes: 13 additions & 3 deletions grand/backends/_networkx.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,19 @@ def get_node_count(self) -> int:
"""
return len(self._nx_graph)

def get_edge_count(self) -> int:
"""
Get an integer count of the number of edges in this graph.
Arguments:
None
Returns:
int: The count of edges
"""
return len(self._nx_graph.edges)

def ingest_from_edgelist_dataframe(
self, edgelist: pd.DataFrame, source_column: str, target_column: str
) -> dict:
Expand Down Expand Up @@ -200,6 +213,3 @@ def ingest_from_edgelist_dataframe(
"edge_count": len(edgelist),
"edge_duration": time.time() - tic,
}

def teardown(self) -> None:
return
5 changes: 1 addition & 4 deletions grand/backends/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,18 +295,15 @@ def out_degrees(self, nbunch=None) -> Collection:


class CachedBackend(Backend):

"""
A proxy Backend that serves as a cache for any other grand.Backend.
"""

def __init__(self, backend: Backend):
...
def __init__(self, backend: Backend): ...


class InMemoryCachedBackend(CachedBackend):

"""
A proxy Backend that serves as a cache for any other grand.Backend.
Expand Down
8 changes: 8 additions & 0 deletions grand/backends/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,11 @@ def test_directed_degree_multiple(self, backend):
assert G.nx.in_degree("foo") == 0
assert G.nx.in_degree("bar") == 1
assert G.nx.in_degree("baz") == 1

def test_node_count(self, backend):
backend, kwargs = backend
G = Graph(backend=backend(**kwargs))
G.nx.add_node("foo", bar=True)
G.nx.add_node("bar", foo=True)
assert len(G.nx) == 2

9 changes: 6 additions & 3 deletions grand/dialects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ def out_degree(self, nbunch=None):
def is_directed(self):
return self.parent.backend.is_directed()

def __len__(self):
return self.parent.backend.get_node_count()


class IGraphDialect(nx.Graph):
"""
Expand Down Expand Up @@ -218,7 +221,7 @@ def es(self):
]

def add_edges(self, edgelist: List[Tuple[Hashable, Hashable]]):
for (u, v) in edgelist:
for u, v in edgelist:
self.parent.backend.add_edge(u, v, {})

def get_edgelist(self):
Expand Down Expand Up @@ -279,7 +282,7 @@ def degreeOut(self, v):

def density(self):
# TODO: implement backend#degree?
E = len(self.parent.backend.all_edges_as_iterable())
E = self.parent.backend.get_edge_count()
V = self.parent.backend.get_node_count()

if self.parent.backend.is_directed():
Expand All @@ -291,7 +294,7 @@ def numberOfNodes(self) -> int:
return self.parent.backend.get_node_count()

def numberOfEdges(self) -> int:
return len(self.parent.backend.all_edges_as_iterable())
return self.parent.backend.get_edge_count()

def removeEdge(self, u, v) -> None:
raise NotImplementedError
Expand Down

0 comments on commit 41657e1

Please sign in to comment.