Spaces:
Running
Running
Simple graph sampling.
Browse files- server/lynxkite_ops.py +19 -4
- server/networkx_ops.py +1 -1
- server/ops.py +6 -0
server/lynxkite_ops.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
'''Some operations. To be split into separate files when we have more.'''
|
| 2 |
from . import ops
|
|
|
|
| 3 |
import dataclasses
|
| 4 |
import functools
|
| 5 |
import matplotlib
|
|
@@ -145,12 +146,26 @@ def create_scale_free_graph(*, nodes: int = 10):
|
|
| 145 |
def compute_pagerank(graph: nx.Graph, *, damping=0.85, iterations=100):
|
| 146 |
return nx.pagerank(graph, alpha=damping, max_iter=iterations)
|
| 147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
@op("Sample graph")
|
| 150 |
def sample_graph(graph: nx.Graph, *, nodes: int = 100):
|
| 151 |
-
'''Takes a subgraph.'''
|
| 152 |
-
|
| 153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
|
| 155 |
def _map_color(value):
|
| 156 |
cmap = matplotlib.cm.get_cmap('viridis')
|
|
@@ -159,7 +174,7 @@ def _map_color(value):
|
|
| 159 |
return ['#{:02x}{:02x}{:02x}'.format(int(r*255), int(g*255), int(b*255)) for r, g, b in rgba[:, :3]]
|
| 160 |
|
| 161 |
@op("Visualize graph", view="visualization")
|
| 162 |
-
def visualize_graph(graph: Bundle, *, color_nodes_by:
|
| 163 |
nodes = graph.dfs['nodes'].copy()
|
| 164 |
if color_nodes_by:
|
| 165 |
nodes['color'] = _map_color(nodes[color_nodes_by])
|
|
|
|
| 1 |
'''Some operations. To be split into separate files when we have more.'''
|
| 2 |
from . import ops
|
| 3 |
+
from collections import deque
|
| 4 |
import dataclasses
|
| 5 |
import functools
|
| 6 |
import matplotlib
|
|
|
|
| 146 |
def compute_pagerank(graph: nx.Graph, *, damping=0.85, iterations=100):
|
| 147 |
return nx.pagerank(graph, alpha=damping, max_iter=iterations)
|
| 148 |
|
| 149 |
+
@op("Discard loop edges")
|
| 150 |
+
def discard_loop_edges(graph: nx.Graph):
|
| 151 |
+
graph = graph.copy()
|
| 152 |
+
graph.remove_edges_from(nx.selfloop_edges(graph))
|
| 153 |
+
return graph
|
| 154 |
|
| 155 |
@op("Sample graph")
|
| 156 |
def sample_graph(graph: nx.Graph, *, nodes: int = 100):
|
| 157 |
+
'''Takes a (preferably connected) subgraph.'''
|
| 158 |
+
sample = set()
|
| 159 |
+
to_expand = deque([0])
|
| 160 |
+
while to_expand and len(sample) < nodes:
|
| 161 |
+
node = to_expand.pop()
|
| 162 |
+
for n in graph.neighbors(node):
|
| 163 |
+
if n not in sample:
|
| 164 |
+
sample.add(n)
|
| 165 |
+
to_expand.append(n)
|
| 166 |
+
if len(sample) == nodes:
|
| 167 |
+
break
|
| 168 |
+
return nx.Graph(graph.subgraph(sample))
|
| 169 |
|
| 170 |
def _map_color(value):
|
| 171 |
cmap = matplotlib.cm.get_cmap('viridis')
|
|
|
|
| 174 |
return ['#{:02x}{:02x}{:02x}'.format(int(r*255), int(g*255), int(b*255)) for r, g, b in rgba[:, :3]]
|
| 175 |
|
| 176 |
@op("Visualize graph", view="visualization")
|
| 177 |
+
def visualize_graph(graph: Bundle, *, color_nodes_by: ops.NodeAttribute = None):
|
| 178 |
nodes = graph.dfs['nodes'].copy()
|
| 179 |
if color_nodes_by:
|
| 180 |
nodes['color'] = _map_color(nodes[color_nodes_by])
|
server/networkx_ops.py
CHANGED
|
@@ -16,7 +16,7 @@ def wrapped(name: str, func):
|
|
| 16 |
return res
|
| 17 |
# Otherwise it's a node attribute.
|
| 18 |
graph = args[0].copy()
|
| 19 |
-
nx.set_node_attributes(graph,
|
| 20 |
return graph
|
| 21 |
return wrapper
|
| 22 |
|
|
|
|
| 16 |
return res
|
| 17 |
# Otherwise it's a node attribute.
|
| 18 |
graph = args[0].copy()
|
| 19 |
+
nx.set_node_attributes(graph, values=res, name=name)
|
| 20 |
return graph
|
| 21 |
return wrapper
|
| 22 |
|
server/ops.py
CHANGED
|
@@ -29,6 +29,12 @@ PathStr = Annotated[
|
|
| 29 |
CollapsedStr = Annotated[
|
| 30 |
str, {'format': 'collapsed'}
|
| 31 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
class BaseConfig(pydantic.BaseModel):
|
| 33 |
model_config = pydantic.ConfigDict(
|
| 34 |
arbitrary_types_allowed=True,
|
|
|
|
| 29 |
CollapsedStr = Annotated[
|
| 30 |
str, {'format': 'collapsed'}
|
| 31 |
]
|
| 32 |
+
NodeAttribute = Annotated[
|
| 33 |
+
str, {'format': 'node attribute'}
|
| 34 |
+
]
|
| 35 |
+
EdgeAttribute = Annotated[
|
| 36 |
+
str, {'format': 'edge attribute'}
|
| 37 |
+
]
|
| 38 |
class BaseConfig(pydantic.BaseModel):
|
| 39 |
model_config = pydantic.ConfigDict(
|
| 40 |
arbitrary_types_allowed=True,
|