Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f9f1ff4
initial commit
Schefflera-Arboricola Jan 17, 2024
d7fcf95
rm extra docs
Schefflera-Arboricola Jan 19, 2024
fcf6612
added unweighted.py rm johnson and all non all_pairs_ algos from weig…
Schefflera-Arboricola Jan 23, 2024
1f68d7d
added all_pairs_node_connectivity
Schefflera-Arboricola Jan 23, 2024
94de91f
Update weighted.py
Schefflera-Arboricola Jan 24, 2024
485270d
modifying G
Schefflera-Arboricola Jan 25, 2024
a6a8f0a
fixed all_pairs_node_connectivity
Schefflera-Arboricola Jan 26, 2024
0cba23e
un-updated ParallelGraph class
Schefflera-Arboricola Jan 30, 2024
e9c6c06
style fixes
Schefflera-Arboricola Feb 1, 2024
5bc797e
changed all_pairs def
Schefflera-Arboricola Feb 7, 2024
414f2c8
adding directed to _calculate_all_pairs_node_connectivity_subset
Schefflera-Arboricola Feb 7, 2024
4f8a751
updated docs of all funcs
Schefflera-Arboricola Feb 8, 2024
00b310b
style fix
Schefflera-Arboricola Feb 8, 2024
20ec806
added benchmarks
Schefflera-Arboricola Feb 8, 2024
01e42ac
style fix
Schefflera-Arboricola Feb 8, 2024
bbbc5f2
added 6 heatmaps(no speedups in 3)
Schefflera-Arboricola Feb 18, 2024
cbda3e8
used loky backend in approximation.connectivity.all_pairs_node_connec…
Schefflera-Arboricola Feb 24, 2024
c7a341b
added get_chunks to shortest paths algos
Schefflera-Arboricola Feb 26, 2024
95b9217
added chunking in all_pairs_node_connectivity, added benchmarks, fixe…
Schefflera-Arboricola Feb 26, 2024
a96dbff
updated docstrings of all 9 funcs
Schefflera-Arboricola Feb 26, 2024
34ef348
Merge branch 'main' into shortest_paths
dschult Mar 10, 2024
07db6dc
Merge branch 'main' into shortest_paths
dschult Mar 11, 2024
5c28ad1
typo fix
Schefflera-Arboricola Mar 11, 2024
e0c000b
Merge branch 'main' into shortest_paths
Schefflera-Arboricola Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nx_parallel/algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# subpackages
from .centrality import *
from .shortest_paths import *
from .approximation import *

# modules
from .efficiency_measures import *
Expand Down
1 change: 1 addition & 0 deletions nx_parallel/algorithms/approximation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .connectivity import *
51 changes: 51 additions & 0 deletions nx_parallel/algorithms/approximation/connectivity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Parallel implementations of fast approximation for node connectivity"""
import itertools
from joblib import Parallel, delayed
import nx_parallel as nxp
from networkx.algorithms.approximation.connectivity import local_node_connectivity

__all__ = [
"all_pairs_node_connectivity",
]


def all_pairs_node_connectivity(G, nbunch=None, cutoff=None):
def _calculate_all_pairs_node_connectivity_subset(chunk):
for u, v in chunk:
k = local_node_connectivity(G, u, v, cutoff=cutoff)
all_pairs[u][v] = k
if not directed:
all_pairs[v][u] = k

if hasattr(G, "graph_object"):
G = G.graph_object

if nbunch is None:
nbunch = G
else:
nbunch = set(nbunch)

directed = G.is_directed()
if directed:
iter_func = itertools.permutations
else:
iter_func = itertools.combinations

pairs = list(iter_func(nbunch, 2))

all_pairs = {}
for u, v in pairs:
all_pairs.setdefault(u, {})[v] = None
if not directed:
all_pairs.setdefault(v, {})[u] = None

total_cores = nxp.cpu_count()
num_in_chunk = max(len(pairs) // total_cores, 1)
pair_chunks = nxp.chunks(pairs, num_in_chunk)

Parallel(n_jobs=total_cores, backend="threading")(
delayed(_calculate_all_pairs_node_connectivity_subset)(chunk)
for chunk in pair_chunks
)

return all_pairs
1 change: 1 addition & 0 deletions nx_parallel/algorithms/shortest_paths/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .weighted import *
from .unweighted import *
49 changes: 49 additions & 0 deletions nx_parallel/algorithms/shortest_paths/unweighted.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# TODO : update docstrings

"""
Shortest path parallel algorithms for unweighted graphs.
"""

from joblib import Parallel, delayed
import nx_parallel as nxp
from networkx.algorithms.shortest_paths.unweighted import (
single_source_shortest_path_length,
single_source_shortest_path,
)

__all__ = [
"all_pairs_shortest_path",
"all_pairs_shortest_path_length",
]


def all_pairs_shortest_path_length(G, cutoff=None):
"""Computes the shortest path lengths between all nodes in `G`."""
if hasattr(G, "graph_object"):
G = G.graph_object

length = single_source_shortest_path_length

def _calculate_all_pairs_shortest_path_length_subset(n):
return (n, (length(G, n, cutoff=cutoff)))

total_cores = nxp.cpu_count()

return Parallel(n_jobs=total_cores, return_as="generator")(
delayed(_calculate_all_pairs_shortest_path_length_subset)(n) for n in G
)


def all_pairs_shortest_path(G, cutoff=None):
"""Compute shortest paths between all nodes."""
if hasattr(G, "graph_object"):
G = G.graph_object

def _calculate_all_pairs_shortest_path_subset(n):
return (n, (single_source_shortest_path(G, n, cutoff=cutoff)))

total_cores = nxp.cpu_count()

return Parallel(n_jobs=total_cores, return_as="generator")(
delayed(_calculate_all_pairs_shortest_path_subset)(n) for n in G
)
83 changes: 81 additions & 2 deletions nx_parallel/algorithms/shortest_paths/weighted.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,87 @@
# TODO : update docstrings

"""
Shortest path parallel algorithms for weighted graphs.
"""

from joblib import Parallel, delayed
from networkx.algorithms.shortest_paths.weighted import single_source_bellman_ford_path
import nx_parallel as nxp
from networkx.algorithms.shortest_paths.weighted import (
single_source_dijkstra,
single_source_dijkstra_path_length,
single_source_dijkstra_path,
single_source_bellman_ford_path,
single_source_bellman_ford_path_length,
)

__all__ = [
"all_pairs_dijkstra",
"all_pairs_dijkstra_path_length",
"all_pairs_dijkstra_path",
"all_pairs_bellman_ford_path_length",
"all_pairs_bellman_ford_path",
]


def all_pairs_dijkstra(G, cutoff=None, weight="weight"):
"""Find shortest weighted paths and lengths between all nodes."""

def _calculate_all_pairs_dijkstra_subset(n):
return (n, single_source_dijkstra(G, n, cutoff=cutoff, weight=weight))

if hasattr(G, "graph_object"):
G = G.graph_object

__all__ = ["all_pairs_bellman_ford_path"]
return Parallel(n_jobs=-1, return_as="generator")(
delayed(_calculate_all_pairs_dijkstra_subset)(n) for n in G
)


def all_pairs_dijkstra_path_length(G, cutoff=None, weight="weight"):
"""Compute shortest path lengths between all nodes in a weighted graph."""
if hasattr(G, "graph_object"):
G = G.graph_object

length = single_source_dijkstra_path_length

def _calculate_all_pairs_dijkstra_path_length_subset(n):
return (n, length(G, n, cutoff=cutoff, weight=weight))

return Parallel(n_jobs=-1, return_as="generator")(
delayed(_calculate_all_pairs_dijkstra_path_length_subset)(n) for n in G
)


def all_pairs_dijkstra_path(G, cutoff=None, weight="weight"):
"""Compute shortest paths between all nodes in a weighted graph."""
if hasattr(G, "graph_object"):
G = G.graph_object

path = single_source_dijkstra_path

def _calculate_all_pairs_dijkstra_path_subset(n):
return (n, path(G, n, cutoff=cutoff, weight=weight))

return Parallel(n_jobs=-1, return_as="generator")(
delayed(_calculate_all_pairs_dijkstra_path_subset)(n) for n in G
)


def all_pairs_bellman_ford_path_length(G, weight="weight"):
"""Compute shortest path lengths between all nodes in a weighted graph."""

def _calculate_shortest_paths_length_subset(n):
return (n, length(G, n, weight=weight))

if hasattr(G, "graph_object"):
G = G.graph_object

length = single_source_bellman_ford_path_length

distance = Parallel(n_jobs=-1, return_as="generator")(
delayed(_calculate_shortest_paths_length_subset)(n) for n in G
)
return distance


def all_pairs_bellman_ford_path(G, weight="weight"):
Expand Down
28 changes: 26 additions & 2 deletions nx_parallel/interface.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
from nx_parallel.algorithms.centrality.betweenness import betweenness_centrality
from nx_parallel.algorithms.shortest_paths.weighted import all_pairs_bellman_ford_path
from nx_parallel.algorithms.shortest_paths.weighted import (
all_pairs_dijkstra,
all_pairs_dijkstra_path_length,
all_pairs_dijkstra_path,
all_pairs_bellman_ford_path_length,
all_pairs_bellman_ford_path,
)
from nx_parallel.algorithms.shortest_paths.unweighted import (
all_pairs_shortest_path,
all_pairs_shortest_path_length,
)
from nx_parallel.algorithms.efficiency_measures import local_efficiency
from nx_parallel.algorithms.isolate import number_of_isolates
from nx_parallel.algorithms.tournament import (
is_reachable,
tournament_is_strongly_connected,
)
from nx_parallel.algorithms.vitality import closeness_vitality
from nx_parallel.algorithms.approximation.connectivity import (
all_pairs_node_connectivity,
)

__all__ = ["Dispatcher", "ParallelGraph"]

Expand Down Expand Up @@ -46,9 +59,20 @@ class Dispatcher:
# Efficiency
local_efficiency = local_efficiency

# Shortest Paths : all pairs shortest paths(bellman_ford)
# Shortest Paths : weighted graphs
all_pairs_dijkstra = all_pairs_dijkstra
all_pairs_dijkstra_path_length = all_pairs_dijkstra_path_length
all_pairs_dijkstra_path = all_pairs_dijkstra_path
all_pairs_bellman_ford_path_length = all_pairs_bellman_ford_path_length
all_pairs_bellman_ford_path = all_pairs_bellman_ford_path

# Shortest Paths : unweighted graphs
all_pairs_shortest_path = all_pairs_shortest_path
all_pairs_shortest_path_length = all_pairs_shortest_path_length

#
approximate_all_pairs_node_connectivity = all_pairs_node_connectivity

# =============================

@staticmethod
Expand Down