48587d6d5e
* Improve NetworkX module import * Add Networkx dependencies to Dockerfiles
826 lines
31 KiB
Python
826 lines
31 KiB
Python
import sys
|
|
import mgp
|
|
try:
|
|
import networkx as nx
|
|
import numpy # noqa E401
|
|
import scipy # noqa E401
|
|
except ImportError as import_error:
|
|
sys.stderr.write((
|
|
'\n'
|
|
'NOTE: Please install networkx, numpy, scipy to be able to '
|
|
'use proxied NetworkX algorithms. E.g., CALL nxalg.pagerank(...).\n'
|
|
'Using Python:\n'
|
|
+ sys.version +
|
|
'\n'))
|
|
raise import_error
|
|
# Imported last because it also depends on networkx.
|
|
from mgp_networkx import (MemgraphMultiDiGraph, MemgraphDiGraph, # noqa: E402
|
|
MemgraphMultiGraph, MemgraphGraph,
|
|
PropertiesDictionary)
|
|
|
|
|
|
# networkx.algorithms.approximation.connectivity.node_connectivity
|
|
@mgp.read_proc
|
|
def node_connectivity(ctx: mgp.ProcCtx,
|
|
source: mgp.Nullable[mgp.Vertex] = None,
|
|
target: mgp.Nullable[mgp.Vertex] = None
|
|
) -> mgp.Record(connectivity=int):
|
|
return mgp.Record(connectivity=nx.node_connectivity(
|
|
MemgraphMultiDiGraph(ctx=ctx), source, target))
|
|
|
|
|
|
# networkx.algorithms.assortativity.degree_assortativity_coefficient
|
|
@mgp.read_proc
|
|
def degree_assortativity_coefficient(
|
|
ctx: mgp.ProcCtx,
|
|
x: str = 'out',
|
|
y: str = 'in',
|
|
weight: mgp.Nullable[str] = None,
|
|
nodes: mgp.Nullable[mgp.List[mgp.Vertex]] = None
|
|
) -> mgp.Record(assortativity=float):
|
|
return mgp.Record(assortativity=nx.degree_assortativity_coefficient(
|
|
MemgraphMultiDiGraph(ctx=ctx), x, y, weight, nodes))
|
|
|
|
|
|
# networkx.algorithms.asteroidal.is_at_free
|
|
@mgp.read_proc
|
|
def is_at_free(ctx: mgp.ProcCtx) -> mgp.Record(is_at_free=bool):
|
|
return mgp.Record(is_at_free=nx.is_at_free(MemgraphGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.bipartite.basic.is_bipartite
|
|
@mgp.read_proc
|
|
def is_bipartite(ctx: mgp.ProcCtx) -> mgp.Record(is_bipartite=bool):
|
|
return mgp.Record(is_bipartite=nx.is_bipartite(
|
|
MemgraphMultiDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.boundary.node_boundary
|
|
@mgp.read_proc
|
|
def node_boundary(ctx: mgp.ProcCtx,
|
|
nbunch1: mgp.List[mgp.Vertex],
|
|
nbunch2: mgp.Nullable[mgp.List[mgp.Vertex]] = None
|
|
) -> mgp.Record(boundary=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(boundary=list(nx.node_boundary(
|
|
MemgraphMultiDiGraph(ctx=ctx), nbunch1, nbunch2)))
|
|
|
|
|
|
# networkx.algorithms.bridges.bridges
|
|
@mgp.read_proc
|
|
def bridges(ctx: mgp.ProcCtx,
|
|
root: mgp.Nullable[mgp.Vertex] = None
|
|
) -> mgp.Record(bridges=mgp.List[mgp.Edge]):
|
|
g = MemgraphMultiGraph(ctx=ctx)
|
|
return mgp.Record(
|
|
bridges=[next(iter(g[u][v]))
|
|
for u, v in nx.bridges(MemgraphGraph(ctx=ctx),
|
|
root=root)])
|
|
|
|
|
|
# networkx.algorithms.centrality.betweenness_centrality
|
|
@mgp.read_proc
|
|
def betweenness_centrality(ctx: mgp.ProcCtx,
|
|
k: mgp.Nullable[int] = None,
|
|
normalized: bool = True,
|
|
weight: mgp.Nullable[str] = None,
|
|
endpoints: bool = False,
|
|
seed: mgp.Nullable[int] = None
|
|
) -> mgp.Record(node=mgp.Vertex,
|
|
betweenness=mgp.Number):
|
|
return [mgp.Record(node=n, betweenness=b)
|
|
for n, b in nx.betweenness_centrality(
|
|
MemgraphDiGraph(ctx=ctx), k=k, normalized=normalized,
|
|
weight=weight, endpoints=endpoints, seed=seed).items()]
|
|
|
|
|
|
# networkx.algorithms.chains.chain_decomposition
|
|
@mgp.read_proc
|
|
def chain_decomposition(ctx: mgp.ProcCtx,
|
|
root: mgp.Nullable[mgp.Vertex] = None
|
|
) -> mgp.Record(chains=mgp.List[mgp.List[mgp.Edge]]):
|
|
g = MemgraphMultiGraph(ctx=ctx)
|
|
return mgp.Record(
|
|
chains=[[next(iter(g[u][v])) for u, v in d]
|
|
for d in nx.chain_decomposition(MemgraphGraph(ctx=ctx),
|
|
root=root)])
|
|
|
|
|
|
# networkx.algorithms.chordal.is_chordal
|
|
@mgp.read_proc
|
|
def is_chordal(ctx: mgp.ProcCtx) -> mgp.Record(is_chordal=bool):
|
|
return mgp.Record(is_chordal=nx.is_chordal(MemgraphGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.clique.find_cliques
|
|
@mgp.read_proc
|
|
def find_cliques(ctx: mgp.ProcCtx
|
|
) -> mgp.Record(cliques=mgp.List[mgp.List[mgp.Vertex]]):
|
|
return mgp.Record(cliques=list(nx.find_cliques(
|
|
MemgraphMultiGraph(ctx=ctx))))
|
|
|
|
|
|
# networkx.algorithms.cluster.clustering
|
|
@mgp.read_proc
|
|
def clustering(ctx: mgp.ProcCtx,
|
|
nodes: mgp.Nullable[mgp.List[mgp.Vertex]] = None,
|
|
weight: mgp.Nullable[str] = None
|
|
) -> mgp.Record(node=mgp.Vertex, clustering=mgp.Number):
|
|
return [mgp.Record(node=n, clustering=c)
|
|
for n, c in nx.clustering(
|
|
MemgraphDiGraph(ctx=ctx), nodes=nodes,
|
|
weight=weight).items()]
|
|
|
|
|
|
# networkx.algorithms.coloring.greedy_color
|
|
@mgp.read_proc
|
|
def greedy_color(ctx: mgp.ProcCtx,
|
|
strategy: str = 'largest_first',
|
|
interchange: bool = False
|
|
) -> mgp.Record(node=mgp.Vertex, color=int):
|
|
return [mgp.Record(node=n, color=c) for n, c in nx.greedy_color(
|
|
MemgraphMultiDiGraph(ctx=ctx), strategy, interchange).items()]
|
|
|
|
|
|
# networkx.algorithms.communicability_alg.communicability
|
|
@mgp.read_proc
|
|
def communicability(ctx: mgp.ProcCtx
|
|
) -> mgp.Record(node1=mgp.Vertex, node2=mgp.Vertex,
|
|
communicability=mgp.Number):
|
|
return [mgp.Record(node1=n1, node2=n2, communicability=v)
|
|
for n1, d in nx.communicability(MemgraphGraph(ctx=ctx)).items()
|
|
for n2, v in d.items()]
|
|
|
|
|
|
# networkx.algorithms.community.kclique.k_clique_communities
|
|
@mgp.read_proc
|
|
def k_clique_communities(
|
|
ctx: mgp.ProcCtx,
|
|
k: int,
|
|
cliques: mgp.Nullable[mgp.List[mgp.List[mgp.Vertex]]] = None
|
|
) -> mgp.Record(communities=mgp.List[mgp.List[mgp.Vertex]]):
|
|
return mgp.Record(communities=[
|
|
list(s) for s in nx.community.k_clique_communities(
|
|
MemgraphMultiGraph(ctx=ctx), k, cliques)])
|
|
|
|
|
|
# networkx.algorithms.approximation.kcomponents.k_components
|
|
@mgp.read_proc
|
|
def k_components(ctx: mgp.ProcCtx,
|
|
density: mgp.Number = 0.95
|
|
) -> mgp.Record(k=int,
|
|
components=mgp.List[mgp.List[mgp.Vertex]]):
|
|
kcomps = nx.k_components(MemgraphMultiGraph(ctx=ctx), density)
|
|
|
|
return [mgp.Record(k=k, components=[list(s) for s in comps])
|
|
for k, comps in kcomps.items()]
|
|
|
|
|
|
# networkx.algorithms.components.biconnected_components
|
|
@mgp.read_proc
|
|
def biconnected_components(
|
|
ctx: mgp.ProcCtx
|
|
) -> mgp.Record(components=mgp.List[mgp.List[mgp.Vertex]]):
|
|
comps = nx.biconnected_components(MemgraphMultiGraph(ctx=ctx))
|
|
return mgp.Record(components=[list(s) for s in comps])
|
|
|
|
|
|
# networkx.algorithms.components.strongly_connected_components
|
|
@mgp.read_proc
|
|
def strongly_connected_components(
|
|
ctx: mgp.ProcCtx
|
|
) -> mgp.Record(components=mgp.List[mgp.List[mgp.Vertex]]):
|
|
comps = nx.strongly_connected_components(MemgraphMultiDiGraph(ctx=ctx))
|
|
return mgp.Record(components=[list(s) for s in comps])
|
|
|
|
|
|
# networkx.algorithms.connectivity.edge_kcomponents.k_edge_components
|
|
#
|
|
# NOTE: NetworkX 2.4, algorithms/connectivity/edge_kcompnents.py:367. We create
|
|
# a *copy* of the graph because the algorithm copies the graph using
|
|
# __class__() and tries to modify it.
|
|
@mgp.read_proc
|
|
def k_edge_components(
|
|
ctx: mgp.ProcCtx,
|
|
k: int
|
|
) -> mgp.Record(components=mgp.List[mgp.List[mgp.Vertex]]):
|
|
return mgp.Record(components=[list(s) for s in nx.k_edge_components(
|
|
nx.DiGraph(MemgraphDiGraph(ctx=ctx)), k)])
|
|
|
|
|
|
# networkx.algorithms.core.core_number
|
|
@mgp.read_proc
|
|
def core_number(ctx: mgp.ProcCtx
|
|
) -> mgp.Record(node=mgp.Vertex, core=mgp.Number):
|
|
return [mgp.Record(node=n, core=c)
|
|
for n, c in nx.core_number(MemgraphDiGraph(ctx=ctx)).items()]
|
|
|
|
|
|
# networkx.algorithms.covering.is_edge_cover
|
|
@mgp.read_proc
|
|
def is_edge_cover(ctx: mgp.ProcCtx, cover: mgp.List[mgp.Edge]
|
|
) -> mgp.Record(is_edge_cover=bool):
|
|
cover = set([(e.from_vertex, e.to_vertex) for e in cover])
|
|
return mgp.Record(is_edge_cover=nx.is_edge_cover(
|
|
MemgraphMultiGraph(ctx=ctx), cover))
|
|
|
|
|
|
# networkx.algorithms.cycles.find_cycle
|
|
@mgp.read_proc
|
|
def find_cycle(ctx: mgp.ProcCtx,
|
|
source: mgp.Nullable[mgp.List[mgp.Vertex]] = None,
|
|
orientation: mgp.Nullable[str] = None
|
|
) -> mgp.Record(cycle=mgp.Nullable[mgp.List[mgp.Edge]]):
|
|
try:
|
|
return mgp.Record(cycle=[e for _, _, e in nx.find_cycle(
|
|
MemgraphMultiDiGraph(ctx=ctx), source, orientation)])
|
|
except nx.NetworkXNoCycle:
|
|
return mgp.Record(cycle=None)
|
|
|
|
|
|
# networkx.algorithms.cycles.simple_cycles
|
|
#
|
|
# NOTE: NetworkX 2.4, algorithms/cycles.py:183. We create a *copy* of the graph
|
|
# because the algorithm copies the graph using type() and tries to pass initial
|
|
# data.
|
|
@mgp.read_proc
|
|
def simple_cycles(ctx: mgp.ProcCtx
|
|
) -> mgp.Record(cycles=mgp.List[mgp.List[mgp.Vertex]]):
|
|
return mgp.Record(cycles=list(nx.simple_cycles(
|
|
nx.MultiDiGraph(MemgraphMultiDiGraph(ctx=ctx)).copy())))
|
|
|
|
|
|
# networkx.algorithms.cuts.node_expansion
|
|
@mgp.read_proc
|
|
def node_expansion(ctx: mgp.ProcCtx, s: mgp.List[mgp.Vertex]
|
|
) -> mgp.Record(node_expansion=mgp.Number):
|
|
return mgp.Record(node_expansion=nx.node_expansion(
|
|
MemgraphMultiDiGraph(ctx=ctx), set(s)))
|
|
|
|
|
|
# networkx.algorithms.dag.topological_sort
|
|
@mgp.read_proc
|
|
def topological_sort(ctx: mgp.ProcCtx
|
|
) -> mgp.Record(nodes=mgp.Nullable[mgp.List[mgp.Vertex]]):
|
|
return mgp.Record(nodes=list(nx.topological_sort(
|
|
MemgraphMultiDiGraph(ctx=ctx))))
|
|
|
|
|
|
# networkx.algorithms.dag.ancestors
|
|
@mgp.read_proc
|
|
def ancestors(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex
|
|
) -> mgp.Record(ancestors=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(ancestors=list(nx.ancestors(
|
|
MemgraphMultiDiGraph(ctx=ctx), source)))
|
|
|
|
|
|
# networkx.algorithms.dag.descendants
|
|
@mgp.read_proc
|
|
def descendants(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex
|
|
) -> mgp.Record(descendants=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(descendants=list(nx.descendants(
|
|
MemgraphMultiDiGraph(ctx=ctx), source)))
|
|
|
|
|
|
# networkx.algorithms.distance_measures.center
|
|
#
|
|
# NOTE: Takes more parameters.
|
|
@mgp.read_proc
|
|
def center(ctx: mgp.ProcCtx) -> mgp.Record(center=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(center=list(nx.center(MemgraphMultiDiGraph(ctx=ctx))))
|
|
|
|
|
|
# networkx.algorithms.distance_measures.diameter
|
|
#
|
|
# NOTE: Takes more parameters.
|
|
@mgp.read_proc
|
|
def diameter(ctx: mgp.ProcCtx) -> mgp.Record(diameter=int):
|
|
return mgp.Record(diameter=nx.diameter(MemgraphMultiDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.distance_regular.is_distance_regular
|
|
@mgp.read_proc
|
|
def is_distance_regular(ctx: mgp.ProcCtx
|
|
) -> mgp.Record(is_distance_regular=bool):
|
|
return mgp.Record(is_distance_regular=nx.is_distance_regular(
|
|
MemgraphMultiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.strongly_regular.is_strongly_regular
|
|
@mgp.read_proc
|
|
def is_strongly_regular(ctx: mgp.ProcCtx
|
|
) -> mgp.Record(is_strongly_regular=bool):
|
|
return mgp.Record(is_strongly_regular=nx.is_strongly_regular(
|
|
MemgraphMultiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.dominance.dominance_frontiers
|
|
@mgp.read_proc
|
|
def dominance_frontiers(ctx: mgp.ProcCtx, start: mgp.Vertex,
|
|
) -> mgp.Record(node=mgp.Vertex,
|
|
frontier=mgp.List[mgp.Vertex]):
|
|
return [mgp.Record(node=n, frontier=list(f))
|
|
for n, f in nx.dominance_frontiers(
|
|
MemgraphMultiDiGraph(ctx=ctx), start).items()]
|
|
|
|
|
|
# networkx.algorithms.dominance.immediate_dominatorss
|
|
@mgp.read_proc
|
|
def immediate_dominators(ctx: mgp.ProcCtx, start: mgp.Vertex,
|
|
) -> mgp.Record(node=mgp.Vertex,
|
|
dominator=mgp.Vertex):
|
|
return [mgp.Record(node=n, dominator=d)
|
|
for n, d in nx.immediate_dominators(
|
|
MemgraphMultiDiGraph(ctx=ctx), start).items()]
|
|
|
|
|
|
# networkx.algorithms.dominating.dominating_set
|
|
@mgp.read_proc
|
|
def dominating_set(ctx: mgp.ProcCtx, start: mgp.Vertex,
|
|
) -> mgp.Record(dominating_set=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(dominating_set=list(nx.dominating_set(
|
|
MemgraphMultiDiGraph(ctx=ctx), start)))
|
|
|
|
|
|
# networkx.algorithms.efficiency_measures.local_efficiency
|
|
@mgp.read_proc
|
|
def local_efficiency(ctx: mgp.ProcCtx) -> mgp.Record(local_efficiency=float):
|
|
return mgp.Record(local_efficiency=nx.local_efficiency(
|
|
MemgraphMultiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.efficiency_measures.global_efficiency
|
|
@mgp.read_proc
|
|
def global_efficiency(ctx: mgp.ProcCtx) -> mgp.Record(global_efficiency=float):
|
|
return mgp.Record(global_efficiency=nx.global_efficiency(
|
|
MemgraphMultiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.euler.is_eulerian
|
|
@mgp.read_proc
|
|
def is_eulerian(ctx: mgp.ProcCtx) -> mgp.Record(is_eulerian=bool):
|
|
return mgp.Record(is_eulerian=nx.is_eulerian(
|
|
MemgraphMultiDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.euler.is_semieulerian
|
|
@mgp.read_proc
|
|
def is_semieulerian(ctx: mgp.ProcCtx) -> mgp.Record(is_semieulerian=bool):
|
|
return mgp.Record(is_semieulerian=nx.is_semieulerian(
|
|
MemgraphMultiDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.euler.has_eulerian_path
|
|
@mgp.read_proc
|
|
def has_eulerian_path(ctx: mgp.ProcCtx) -> mgp.Record(has_eulerian_path=bool):
|
|
return mgp.Record(has_eulerian_path=nx.has_eulerian_path(
|
|
MemgraphMultiDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.hierarchy.flow_hierarchy
|
|
@mgp.read_proc
|
|
def flow_hierarchy(ctx: mgp.ProcCtx,
|
|
weight: mgp.Nullable[str] = None
|
|
) -> mgp.Record(flow_hierarchy=float):
|
|
return mgp.Record(flow_hierarchy=nx.flow_hierarchy(
|
|
MemgraphMultiDiGraph(ctx=ctx), weight=weight))
|
|
|
|
|
|
# networkx.algorithms.isolate.isolates
|
|
@mgp.read_proc
|
|
def isolates(ctx: mgp.ProcCtx) -> mgp.Record(isolates=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(isolates=list(nx.isolates(
|
|
MemgraphMultiDiGraph(ctx=ctx))))
|
|
|
|
|
|
# networkx.algorithms.isolate.is_isolate
|
|
@mgp.read_proc
|
|
def is_isolate(ctx: mgp.ProcCtx, n: mgp.Vertex
|
|
) -> mgp.Record(is_isolate=bool):
|
|
return mgp.Record(is_isolate=nx.is_isolate(
|
|
MemgraphMultiDiGraph(ctx=ctx), n))
|
|
|
|
|
|
# networkx.algorithms.isomorphism.is_isomorphic
|
|
@mgp.read_proc
|
|
def is_isomorphic(ctx: mgp.ProcCtx,
|
|
nodes1: mgp.List[mgp.Vertex],
|
|
edges1: mgp.List[mgp.Edge],
|
|
nodes2: mgp.List[mgp.Vertex],
|
|
edges2: mgp.List[mgp.Edge]
|
|
) -> mgp.Record(is_isomorphic=bool):
|
|
nodes1, edges1, nodes2, edges2 = map(set, [nodes1, edges1, nodes2, edges2])
|
|
g = MemgraphMultiDiGraph(ctx=ctx)
|
|
g1 = nx.subgraph_view(
|
|
g, lambda n: n in nodes1, lambda n1, n2, e: e in edges1)
|
|
g2 = nx.subgraph_view(
|
|
g, lambda n: n in nodes2, lambda n1, n2, e: e in edges2)
|
|
return mgp.Record(is_isomorphic=nx.is_isomorphic(g1, g2))
|
|
|
|
|
|
# networkx.algorithms.link_analysis.pagerank_alg.pagerank
|
|
@mgp.read_proc
|
|
def pagerank(ctx: mgp.ProcCtx,
|
|
alpha: mgp.Number = 0.85,
|
|
personalization: mgp.Nullable[str] = None,
|
|
max_iter: int = 100,
|
|
tol: mgp.Number = 1e-06,
|
|
nstart: mgp.Nullable[str] = None,
|
|
weight: mgp.Nullable[str] = 'weight',
|
|
dangling: mgp.Nullable[str] = None,
|
|
) -> mgp.Record(node=mgp.Vertex, rank=float):
|
|
def to_properties_dictionary(prop):
|
|
return None if prop is None else PropertiesDictionary(ctx, prop)
|
|
|
|
pg = nx.pagerank(MemgraphDiGraph(ctx=ctx), alpha=alpha,
|
|
personalization=to_properties_dictionary(personalization),
|
|
max_iter=max_iter, tol=tol,
|
|
nstart=to_properties_dictionary(nstart), weight=weight,
|
|
dangling=to_properties_dictionary(dangling))
|
|
|
|
return [mgp.Record(node=k, rank=v) for k, v in pg.items()]
|
|
|
|
|
|
# networkx.algorithms.link_prediction.jaccard_coefficient
|
|
@mgp.read_proc
|
|
def jaccard_coefficient(
|
|
ctx: mgp.ProcCtx,
|
|
ebunch: mgp.Nullable[mgp.List[mgp.List[mgp.Vertex]]] = None
|
|
) -> mgp.Record(u=mgp.Vertex, v=mgp.Vertex,
|
|
coef=float):
|
|
return [mgp.Record(u=u, v=v, coef=c) for u, v, c
|
|
in nx.jaccard_coefficient(MemgraphGraph(ctx=ctx), ebunch)]
|
|
|
|
|
|
# networkx.algorithms.lowest_common_ancestors.lowest_common_ancestor
|
|
@mgp.read_proc
|
|
def lowest_common_ancestor(ctx: mgp.ProcCtx, node1: mgp.Vertex,
|
|
node2: mgp.Vertex
|
|
) -> mgp.Record(ancestor=mgp.Nullable[mgp.Vertex]):
|
|
return mgp.Record(ancestor=nx.lowest_common_ancestor(
|
|
MemgraphDiGraph(ctx=ctx), node1, node2))
|
|
|
|
|
|
# networkx.algorithms.matching.maximal_matching
|
|
@mgp.read_proc
|
|
def maximal_matching(ctx: mgp.ProcCtx) -> mgp.Record(edges=mgp.List[mgp.Edge]):
|
|
g = MemgraphMultiDiGraph(ctx=ctx)
|
|
return mgp.Record(edges=list(
|
|
next(iter(g[u][v])) for u, v in nx.maximal_matching(g)))
|
|
|
|
|
|
# networkx.algorithms.planarity.check_planarity
|
|
#
|
|
# NOTE: Returns a graph.
|
|
@mgp.read_proc
|
|
def check_planarity(ctx: mgp.ProcCtx) -> mgp.Record(is_planar=bool):
|
|
return mgp.Record(is_planar=nx.check_planarity(
|
|
MemgraphMultiDiGraph(ctx=ctx))[0])
|
|
|
|
|
|
# networkx.algorithms.non_randomness.non_randomness
|
|
@mgp.read_proc
|
|
def non_randomness(ctx: mgp.ProcCtx,
|
|
k: mgp.Nullable[int] = None
|
|
) -> mgp.Record(non_randomness=float,
|
|
relative_non_randomness=float):
|
|
nn, rnn = nx.non_randomness(
|
|
MemgraphGraph(ctx=ctx), k=k)
|
|
return mgp.Record(non_randomness=nn, relative_non_randomness=rnn)
|
|
|
|
|
|
# networkx.algorithms.reciprocity.reciprocity
|
|
@mgp.read_proc
|
|
def reciprocity(ctx: mgp.ProcCtx,
|
|
nodes: mgp.Nullable[mgp.List[mgp.Vertex]] = None
|
|
) -> mgp.Record(node=mgp.Nullable[mgp.Vertex],
|
|
reciprocity=mgp.Nullable[float]):
|
|
rp = nx.reciprocity(MemgraphMultiDiGraph(ctx=ctx), nodes=nodes)
|
|
if nodes is None:
|
|
return mgp.Record(node=None, reciprocity=rp)
|
|
else:
|
|
return [mgp.Record(node=n, reciprocity=r) for n, r in rp.items()]
|
|
|
|
|
|
# networkx.algorithms.shortest_paths.generic.shortest_path
|
|
@mgp.read_proc
|
|
def shortest_path(ctx: mgp.ProcCtx,
|
|
source: mgp.Nullable[mgp.Vertex] = None,
|
|
target: mgp.Nullable[mgp.Vertex] = None,
|
|
weight: mgp.Nullable[str] = None,
|
|
method: str = 'dijkstra'
|
|
) -> mgp.Record(source=mgp.Vertex, target=mgp.Vertex,
|
|
path=mgp.List[mgp.Vertex]):
|
|
sp = nx.shortest_path(MemgraphMultiDiGraph(ctx=ctx), source=source,
|
|
target=target, weight=weight, method=method)
|
|
|
|
if source and target:
|
|
sp = {source: {target: sp}}
|
|
elif source and not target:
|
|
sp = {source: sp}
|
|
elif not source and target:
|
|
sp = {source: {target: p} for source, p in sp.items()}
|
|
|
|
return [mgp.Record(source=s, target=t, path=p)
|
|
for s, d in sp.items()
|
|
for t, p in d.items()]
|
|
|
|
|
|
# networkx.algorithms.shortest_paths.generic.shortest_path_length
|
|
@mgp.read_proc
|
|
def shortest_path_length(ctx: mgp.ProcCtx,
|
|
source: mgp.Nullable[mgp.Vertex] = None,
|
|
target: mgp.Nullable[mgp.Vertex] = None,
|
|
weight: mgp.Nullable[str] = None,
|
|
method: str = 'dijkstra'
|
|
) -> mgp.Record(source=mgp.Vertex, target=mgp.Vertex,
|
|
length=mgp.Number):
|
|
sp = nx.shortest_path_length(MemgraphMultiDiGraph(ctx=ctx), source=source,
|
|
target=target, weight=weight, method=method)
|
|
|
|
if source and target:
|
|
sp = {source: {target: sp}}
|
|
elif source and not target:
|
|
sp = {source: sp}
|
|
elif not source and target:
|
|
sp = {source: {target: l} for source, l in sp.items()}
|
|
else:
|
|
sp = dict(sp)
|
|
|
|
return [mgp.Record(source=s, target=t, length=l)
|
|
for s, d in sp.items()
|
|
for t, l in d.items()]
|
|
|
|
|
|
# networkx.algorithms.shortest_paths.generic.all_shortest_paths
|
|
@mgp.read_proc
|
|
def all_shortest_paths(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
target: mgp.Vertex,
|
|
weight: mgp.Nullable[str] = None,
|
|
method: str = 'dijkstra'
|
|
) -> mgp.Record(paths=mgp.List[mgp.List[mgp.Vertex]]):
|
|
return mgp.Record(paths=list(nx.all_shortest_paths(
|
|
MemgraphMultiDiGraph(ctx=ctx), source=source, target=target,
|
|
weight=weight, method=method)))
|
|
|
|
|
|
# networkx.algorithms.shortest_paths.generic.has_path
|
|
@mgp.read_proc
|
|
def has_path(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
target: mgp.Vertex) -> mgp.Record(has_path=bool):
|
|
return mgp.Record(has_path=nx.has_path(MemgraphMultiDiGraph(ctx=ctx),
|
|
source, target))
|
|
|
|
|
|
# networkx.algorithms.shortest_paths.weighted.multi_source_dijkstra_path
|
|
@mgp.read_proc
|
|
def multi_source_dijkstra_path(ctx: mgp.ProcCtx,
|
|
sources: mgp.List[mgp.Vertex],
|
|
cutoff: mgp.Nullable[int] = None,
|
|
weight: str = 'weight'
|
|
) -> mgp.Record(target=mgp.Vertex,
|
|
path=mgp.List[mgp.Vertex]):
|
|
return [mgp.Record(target=t, path=p)
|
|
for t, p in nx.multi_source_dijkstra_path(
|
|
MemgraphMultiDiGraph(ctx=ctx), sources, cutoff=cutoff,
|
|
weight=weight).items()]
|
|
|
|
|
|
# networkx.algorithms.shortest_paths.weighted.multi_source_dijkstra_path_length
|
|
@mgp.read_proc
|
|
def multi_source_dijkstra_path_length(ctx: mgp.ProcCtx,
|
|
sources: mgp.List[mgp.Vertex],
|
|
cutoff: mgp.Nullable[int] = None,
|
|
weight: str = 'weight'
|
|
) -> mgp.Record(target=mgp.Vertex,
|
|
length=mgp.Number):
|
|
return [mgp.Record(target=t, length=l)
|
|
for t, l in nx.multi_source_dijkstra_path_length(
|
|
MemgraphMultiDiGraph(ctx=ctx), sources, cutoff=cutoff,
|
|
weight=weight).items()]
|
|
|
|
|
|
# networkx.algorithms.simple_paths.is_simple_path
|
|
@mgp.read_proc
|
|
def is_simple_path(ctx: mgp.ProcCtx,
|
|
nodes: mgp.List[mgp.Vertex]
|
|
) -> mgp.Record(is_simple_path=bool):
|
|
return mgp.Record(is_simple_path=nx.is_simple_path(
|
|
MemgraphMultiDiGraph(ctx=ctx), nodes))
|
|
|
|
|
|
# networkx.algorithms.simple_paths.all_simple_paths
|
|
@mgp.read_proc
|
|
def all_simple_paths(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
target: mgp.Vertex,
|
|
cutoff: mgp.Nullable[int] = None
|
|
) -> mgp.Record(paths=mgp.List[mgp.List[mgp.Vertex]]):
|
|
return mgp.Record(paths=list(nx.all_simple_paths(
|
|
MemgraphMultiDiGraph(ctx=ctx), source, target, cutoff=cutoff)))
|
|
|
|
|
|
# networkx.algorithms.tournament.is_tournament
|
|
@mgp.read_proc
|
|
def is_tournament(ctx: mgp.ProcCtx) -> mgp.Record(is_tournament=bool):
|
|
return mgp.Record(is_tournament=nx.tournament.is_tournament(
|
|
MemgraphDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.traversal.breadth_first_search.bfs_edges
|
|
@mgp.read_proc
|
|
def bfs_edges(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
reverse: bool = False,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(edges=mgp.List[mgp.Edge]):
|
|
return mgp.Record(edges=list(nx.bfs_edges(
|
|
MemgraphMultiDiGraph(ctx=ctx), source, reverse=reverse,
|
|
depth_limit=depth_limit)))
|
|
|
|
|
|
# networkx.algorithms.traversal.breadth_first_search.bfs_tree
|
|
@mgp.read_proc
|
|
def bfs_tree(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
reverse: bool = False,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(tree=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(tree=list(nx.bfs_tree(
|
|
MemgraphMultiDiGraph(ctx=ctx), source, reverse=reverse,
|
|
depth_limit=depth_limit)))
|
|
|
|
|
|
# networkx.algorithms.traversal.breadth_first_search.bfs_predecessors
|
|
@mgp.read_proc
|
|
def bfs_predecessors(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(node=mgp.Vertex,
|
|
predecessor=mgp.Vertex):
|
|
return [mgp.Record(node=n, predecessor=p)
|
|
for n, p in nx.bfs_predecessors(
|
|
MemgraphMultiDiGraph(ctx=ctx), source,
|
|
depth_limit=depth_limit)]
|
|
|
|
|
|
# networkx.algorithms.traversal.breadth_first_search.bfs_successors
|
|
@mgp.read_proc
|
|
def bfs_successors(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(node=mgp.Vertex,
|
|
successors=mgp.List[mgp.Vertex]):
|
|
return [mgp.Record(node=n, successors=s)
|
|
for n, s in nx.bfs_successors(
|
|
MemgraphMultiDiGraph(ctx=ctx), source,
|
|
depth_limit=depth_limit)]
|
|
|
|
|
|
# networkx.algorithms.traversal.depth_first_search.dfs_tree
|
|
@mgp.read_proc
|
|
def dfs_tree(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(tree=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(tree=list(nx.dfs_tree(
|
|
MemgraphMultiDiGraph(ctx=ctx), source, depth_limit=depth_limit)))
|
|
|
|
|
|
# networkx.algorithms.traversal.depth_first_search.dfs_predecessors
|
|
@mgp.read_proc
|
|
def dfs_predecessors(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(node=mgp.Vertex,
|
|
predecessor=mgp.Vertex):
|
|
return [mgp.Record(node=n, predecessor=p)
|
|
for n, p in nx.dfs_predecessors(
|
|
MemgraphMultiDiGraph(ctx=ctx), source,
|
|
depth_limit=depth_limit).items()]
|
|
|
|
|
|
# networkx.algorithms.traversal.depth_first_search.dfs_successors
|
|
@mgp.read_proc
|
|
def dfs_successors(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(node=mgp.Vertex,
|
|
successors=mgp.List[mgp.Vertex]):
|
|
return [mgp.Record(node=n, successors=s)
|
|
for n, s in nx.dfs_successors(
|
|
MemgraphMultiDiGraph(ctx=ctx), source,
|
|
depth_limit=depth_limit).items()]
|
|
|
|
|
|
# networkx.algorithms.traversal.depth_first_search.dfs_preorder_nodes
|
|
@mgp.read_proc
|
|
def dfs_preorder_nodes(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(nodes=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(nodes=list(nx.dfs_preorder_nodes(
|
|
MemgraphMultiDiGraph(ctx=ctx), source, depth_limit=depth_limit)))
|
|
|
|
|
|
# networkx.algorithms.traversal.depth_first_search.dfs_postorder_nodes
|
|
@mgp.read_proc
|
|
def dfs_postorder_nodes(ctx: mgp.ProcCtx,
|
|
source: mgp.Vertex,
|
|
depth_limit: mgp.Nullable[int] = None
|
|
) -> mgp.Record(nodes=mgp.List[mgp.Vertex]):
|
|
return mgp.Record(nodes=list(nx.dfs_postorder_nodes(
|
|
MemgraphMultiDiGraph(ctx=ctx), source, depth_limit=depth_limit)))
|
|
|
|
|
|
# networkx.algorithms.traversal.edgebfs.edge_bfs
|
|
@mgp.read_proc
|
|
def edge_bfs(ctx: mgp.ProcCtx,
|
|
source: mgp.Nullable[mgp.Vertex] = None,
|
|
orientation: mgp.Nullable[str] = None
|
|
) -> mgp.Record(edges=mgp.List[mgp.Edge]):
|
|
return mgp.Record(edges=list(e for _, _, e in nx.edge_bfs(
|
|
MemgraphMultiDiGraph(ctx=ctx), source=source,
|
|
orientation=orientation)))
|
|
|
|
|
|
# networkx.algorithms.traversal.edgedfs.edge_dfs
|
|
@mgp.read_proc
|
|
def edge_dfs(ctx: mgp.ProcCtx,
|
|
source: mgp.Nullable[mgp.Vertex] = None,
|
|
orientation: mgp.Nullable[str] = None
|
|
) -> mgp.Record(edges=mgp.List[mgp.Edge]):
|
|
return mgp.Record(edges=list(e for _, _, e in nx.edge_dfs(
|
|
MemgraphMultiDiGraph(ctx=ctx), source=source,
|
|
orientation=orientation)))
|
|
|
|
|
|
# networkx.algorithms.tree.recognition.is_tree
|
|
@mgp.read_proc
|
|
def is_tree(ctx: mgp.ProcCtx) -> mgp.Record(is_tree=bool):
|
|
return mgp.Record(is_tree=nx.is_tree(MemgraphDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.tree.recognition.is_forest
|
|
@mgp.read_proc
|
|
def is_forest(ctx: mgp.ProcCtx) -> mgp.Record(is_forest=bool):
|
|
return mgp.Record(is_forest=nx.is_forest(MemgraphDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.tree.recognition.is_arborescence
|
|
@mgp.read_proc
|
|
def is_arborescence(ctx: mgp.ProcCtx) -> mgp.Record(is_arborescence=bool):
|
|
return mgp.Record(is_arborescence=nx.is_arborescence(
|
|
MemgraphDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.tree.recognition.is_branching
|
|
@mgp.read_proc
|
|
def is_branching(ctx: mgp.ProcCtx) -> mgp.Record(is_branching=bool):
|
|
return mgp.Record(is_branching=nx.is_branching(MemgraphDiGraph(ctx=ctx)))
|
|
|
|
|
|
# networkx.algorithms.tree.mst.minimum_spanning_tree
|
|
@mgp.read_proc
|
|
def minimum_spanning_tree(ctx: mgp.ProcCtx,
|
|
weight: str = 'weight',
|
|
algorithm: str = 'kruskal',
|
|
ignore_nan: bool = False
|
|
) -> mgp.Record(nodes=mgp.List[mgp.Vertex],
|
|
edges=mgp.List[mgp.Edge]):
|
|
gres = nx.minimum_spanning_tree(MemgraphMultiGraph(ctx=ctx),
|
|
weight, algorithm, ignore_nan)
|
|
return mgp.Record(nodes=list(gres.nodes()),
|
|
edges=[e for _, _, e in gres.edges(keys=True)])
|
|
|
|
|
|
# networkx.algorithms.triads.triadic_census
|
|
@mgp.read_proc
|
|
def triadic_census(ctx: mgp.ProcCtx) -> mgp.Record(triad=str, count=int):
|
|
return [mgp.Record(triad=t, count=c)
|
|
for t, c in nx.triadic_census(MemgraphDiGraph(ctx=ctx)).items()]
|
|
|
|
|
|
# networkx.algorithms.voronoi.voronoi_cells
|
|
@mgp.read_proc
|
|
def voronoi_cells(ctx: mgp.ProcCtx,
|
|
center_nodes: mgp.List[mgp.Vertex],
|
|
weight: str = 'weight'
|
|
) -> mgp.Record(center=mgp.Vertex,
|
|
cell=mgp.List[mgp.Vertex]):
|
|
return [mgp.Record(center=c1, cell=list(c2))
|
|
for c1, c2 in nx.voronoi_cells(
|
|
MemgraphMultiDiGraph(ctx=ctx), center_nodes,
|
|
weight=weight).items()]
|
|
|
|
|
|
# networkx.algorithms.wiener.wiener_index
|
|
@mgp.read_proc
|
|
def wiener_index(ctx: mgp.ProcCtx, weight: mgp.Nullable[str] = None
|
|
) -> mgp.Record(wiener_index=mgp.Number):
|
|
return mgp.Record(wiener_index=nx.wiener_index(
|
|
MemgraphMultiDiGraph(ctx=ctx), weight=weight))
|