Skip to content

Commit 452a3e7

Browse files
authored
removed asserts, logging, rename of method (#291)
1 parent b1517f4 commit 452a3e7

11 files changed

Lines changed: 118 additions & 102 deletions

File tree

docs/tutorial/paths_higher_order.ipynb

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@
524524
},
525525
{
526526
"cell_type": "code",
527-
"execution_count": 8,
527+
"execution_count": null,
528528
"metadata": {},
529529
"outputs": [
530530
{
@@ -817,7 +817,7 @@
817817
}
818818
],
819819
"source": [
820-
"m = pp.MultiOrderModel.from_PathData(paths, max_order=1)\n",
820+
"m = pp.MultiOrderModel.from_path_data(paths, max_order=1)\n",
821821
"g = m.layers[1]\n",
822822
"print(g.data.edge_index)\n",
823823
"print(g.data.edge_weight)\n",
@@ -869,7 +869,7 @@
869869
},
870870
{
871871
"cell_type": "code",
872-
"execution_count": 10,
872+
"execution_count": null,
873873
"metadata": {},
874874
"outputs": [
875875
{
@@ -1162,7 +1162,7 @@
11621162
}
11631163
],
11641164
"source": [
1165-
"m = pp.MultiOrderModel.from_PathData(paths_2, max_order=1)\n",
1165+
"m = pp.MultiOrderModel.from_path_data(paths_2, max_order=1)\n",
11661166
"g = m.layers[1]\n",
11671167
"print(g.data.edge_index)\n",
11681168
"print(g.data.edge_weight)\n",
@@ -1186,7 +1186,7 @@
11861186
},
11871187
{
11881188
"cell_type": "code",
1189-
"execution_count": 11,
1189+
"execution_count": null,
11901190
"metadata": {},
11911191
"outputs": [
11921192
{
@@ -1470,7 +1470,7 @@
14701470
}
14711471
],
14721472
"source": [
1473-
"m = pp.MultiOrderModel.from_PathData(paths, max_order=2)\n",
1473+
"m = pp.MultiOrderModel.from_path_data(paths, max_order=2)\n",
14741474
"g = m.layers[2]\n",
14751475
"pp.plot(g, node_label=g.nodes, edge_size=5);"
14761476
]
@@ -1519,7 +1519,7 @@
15191519
},
15201520
{
15211521
"cell_type": "code",
1522-
"execution_count": 13,
1522+
"execution_count": null,
15231523
"metadata": {},
15241524
"outputs": [
15251525
{
@@ -1803,7 +1803,7 @@
18031803
}
18041804
],
18051805
"source": [
1806-
"m = pp.MultiOrderModel.from_PathData(paths_2, max_order=2)\n",
1806+
"m = pp.MultiOrderModel.from_path_data(paths_2, max_order=2)\n",
18071807
"g = m.layers[2]\n",
18081808
"pp.plot(g, node_label=g.nodes);"
18091809
]
@@ -2251,7 +2251,7 @@
22512251
},
22522252
{
22532253
"cell_type": "code",
2254-
"execution_count": 19,
2254+
"execution_count": null,
22552255
"metadata": {},
22562256
"outputs": [
22572257
{
@@ -2271,7 +2271,7 @@
22712271
}
22722272
],
22732273
"source": [
2274-
"m1 = pp.MultiOrderModel.from_PathData(paths, max_order=2)\n",
2274+
"m1 = pp.MultiOrderModel.from_path_data(paths, max_order=2)\n",
22752275
"print(m1.estimate_order(paths, significance_threshold=0.01))"
22762276
]
22772277
},
@@ -2284,7 +2284,7 @@
22842284
},
22852285
{
22862286
"cell_type": "code",
2287-
"execution_count": 20,
2287+
"execution_count": null,
22882288
"metadata": {},
22892289
"outputs": [
22902290
{
@@ -2296,7 +2296,7 @@
22962296
}
22972297
],
22982298
"source": [
2299-
"m2 = pp.MultiOrderModel.from_PathData(paths_2, max_order=2)\n",
2299+
"m2 = pp.MultiOrderModel.from_path_data(paths_2, max_order=2)\n",
23002300
"print(m2.estimate_order(paths_2, significance_threshold=0.01))"
23012301
]
23022302
},
@@ -2309,7 +2309,7 @@
23092309
},
23102310
{
23112311
"cell_type": "code",
2312-
"execution_count": 21,
2312+
"execution_count": null,
23132313
"metadata": {},
23142314
"outputs": [
23152315
{
@@ -2334,7 +2334,7 @@
23342334
"paths_3.append_walk(('b', 'c', 'e'), weight=6.0)\n",
23352335
"paths_3.append_walk(('b', 'c', 'd'), weight=2.0)\n",
23362336
"\n",
2337-
"m3 = pp.MultiOrderModel.from_PathData(paths_3, max_order=2)\n",
2337+
"m3 = pp.MultiOrderModel.from_path_data(paths_3, max_order=2)\n",
23382338
"print(m3.layers[1].data.edge_weight)\n",
23392339
"print(m3.estimate_order(paths_3, significance_threshold=0.01))"
23402340
]
@@ -2372,7 +2372,7 @@
23722372
},
23732373
{
23742374
"cell_type": "code",
2375-
"execution_count": 23,
2375+
"execution_count": null,
23762376
"metadata": {},
23772377
"outputs": [
23782378
{
@@ -2393,7 +2393,7 @@
23932393
"paths_3.append_walk(('b', 'c', 'e'), weight=7.0)\n",
23942394
"paths_3.append_walk(('b', 'c', 'd'), weight=1.0)\n",
23952395
"\n",
2396-
"m3 = pp.MultiOrderModel.from_PathData(paths_3, max_order=2)\n",
2396+
"m3 = pp.MultiOrderModel.from_path_data(paths_3, max_order=2)\n",
23972397
"print(m3.layers[1].data.edge_weight)\n",
23982398
"print(m3.estimate_order(paths_3, significance_threshold=0.01))"
23992399
]
@@ -2457,7 +2457,7 @@
24572457
},
24582458
{
24592459
"cell_type": "code",
2460-
"execution_count": 3,
2460+
"execution_count": null,
24612461
"metadata": {},
24622462
"outputs": [
24632463
{
@@ -2741,7 +2741,7 @@
27412741
}
27422742
],
27432743
"source": [
2744-
"m = pp.MultiOrderModel.from_PathData(paths_tube, max_order=1)\n",
2744+
"m = pp.MultiOrderModel.from_path_data(paths_tube, max_order=1)\n",
27452745
"g = m.layers[1]\n",
27462746
"pp.plot(g, node_label=g.mapping.node_ids.tolist());"
27472747
]
@@ -2755,7 +2755,7 @@
27552755
},
27562756
{
27572757
"cell_type": "code",
2758-
"execution_count": 4,
2758+
"execution_count": null,
27592759
"metadata": {},
27602760
"outputs": [
27612761
{
@@ -2771,7 +2771,7 @@
27712771
],
27722772
"source": [
27732773
"paths_tube.to(device)\n",
2774-
"m = pp.MultiOrderModel.from_PathData(paths_tube, max_order=20)\n",
2774+
"m = pp.MultiOrderModel.from_path_data(paths_tube, max_order=20)\n",
27752775
"print(m.layers[20])"
27762776
]
27772777
},

src/pathpyG/algorithms/centrality.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,6 @@ def path_visitation_probabilities(paths: PathData) -> dict:
152152
Args:
153153
paths: PathData object that contains path data
154154
"""
155-
# if not isinstance(paths, PathData):
156-
# assert False, "`paths` must be an instance of Paths"
157-
# Log.add('Calculating visitation probabilities...', Severity.INFO)
158-
159155
# entries capture the probability that a given node is visited on an arbitrary path
160156
# Note: this is identical to the subpath count of zero-length paths
161157
# (i.e. the relative frequencies of nodes across all pathways)

src/pathpyG/algorithms/generative_models.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@
2222
import torch
2323
from torch_geometric.utils import degree
2424

25+
import logging
26+
2527
from pathpyG.core.graph import Graph
2628
from pathpyG.core.index_map import IndexMap
2729

30+
logger = logging.getLogger("root")
31+
2832

2933
def max_edges(n: int, directed: bool = False, multi_edges: bool = False, self_loops: bool = False) -> int | float:
3034
"""Returns the maximum number of edges that a directed or undirected network with n nodes can
@@ -82,7 +86,9 @@ def erdos_renyi_gnm(n: int, m: int, mapping: IndexMap | None = None,
8286
Returns:
8387
Graph: graph object
8488
"""
85-
assert m <= max_edges(n, directed=directed, self_loops=self_loops, multi_edges=multi_edges)
89+
if m > max_edges(n, directed=directed, self_loops=self_loops, multi_edges=multi_edges):
90+
logger.error("Given number of edges is larger than theoretical maximum")
91+
raise ValueError("Given number of edges is larger than theoretical maximum")
8692

8793
edges = set()
8894
edges_added: int = 0
@@ -186,20 +192,26 @@ def erdos_renyi_gnp_randomize(graph: Graph, self_loops: bool = False) -> Graph:
186192

187193

188194
def erdos_renyi_gnp_likelihood(p: float, graph: Graph) -> float:
189-
"""Calculate the likelihood of parameter p for a G(n,p) model and a given graph"""
190-
assert graph.is_directed() is False
195+
"""Calculate the likelihood of parameter p for a G(n,p) model and a given undirected graph"""
196+
if graph.is_directed():
197+
logger.error("erdos_renyi_gnp_likelihood does not support directed graphs")
198+
raise NotImplementedError("erdos_renyi_gnp_likelihood does not support directed graphs")
191199
return p**graph.n * (1 - p) ** (scipy.special.binom(graph.n, 2) - graph.m)
192200

193201

194202
def erdos_renyi_gnp_log_likelihood(p: float, graph: Graph) -> float:
195-
"""Calculate the log-likelihood of parameter p for a G(n,p) model and a given graph"""
196-
assert graph.is_directed() is False
203+
"""Calculate the log-likelihood of parameter p for a G(n,p) model and a given undirected graph"""
204+
if graph.is_directed():
205+
logger.error("erdos_renyi_gnp_log_likelihood does not support directed graphs")
206+
raise NotImplementedError("erdos_renyi_gnp_log_likelihood does not support directed graphs")
197207
return graph.m * _np.log10(p) + (scipy.special.binom(graph.n, 2) - (graph.m)) * _np.log10(1 - p)
198208

199209

200210
def erdos_renyi_gnp_mle(graph: Graph) -> float:
201211
"""Calculate the maximum likelihood estimate of parameter p for a G(n,p) model and a given undirected graph"""
202-
assert graph.is_directed() is False
212+
if graph.is_directed():
213+
logger.error("erdos_renyi_gnp_mle does not support directed graphs")
214+
raise NotImplementedError("erdos_renyi_gnp_mle does not support directed graphs")
203215
return graph.m / scipy.special.binom(graph.n, 2)
204216

205217

@@ -246,11 +258,12 @@ def watts_strogatz(
246258

247259
if not allow_duplicate_edges:
248260
if n * (n - 1) < edges.shape[1]:
261+
logger.error("number of edges is greater than the number of possible edges in the graph. Set `allow_duplicate_edges=True` to allow this.")
249262
raise ValueError(
250-
"The number of edges is greater than the number of possible edges in the graph. Set `allow_duplicate_edges=True` to allow this."
263+
"number of edges is greater than the number of possible edges in the graph. Set `allow_duplicate_edges=True` to allow this."
251264
)
252265
elif n * (n - 1) * 0.5 < edges.shape[1] and p > 0.3:
253-
warnings.warn(
266+
logger.info(
254267
"Avoding duplicate in graphs with high connectivity and high rewiring probability may be slow. Consider setting `allow_duplicate_edges=True`."
255268
)
256269

@@ -426,7 +439,8 @@ def molloy_reed(degree_sequence: _np.array | Dict[int, float],
426439

427440
# assume that we are given a graphical degree sequence
428441
if not is_graphic_erdos_gallai(degree_sequence):
429-
raise AttributeError('degree sequence is not graphic')
442+
logger.error("given degree sequence is not graphic")
443+
raise ValueError('gicen degree sequence is not graphic')
430444

431445
# create empty network with n nodes
432446
n = len(degree_sequence)
@@ -466,9 +480,10 @@ def molloy_reed(degree_sequence: _np.array | Dict[int, float],
466480

467481

468482
def molloy_reed_randomize(g: Graph) -> Optional[Graph]:
469-
"""Generates a random realization of a given network based on the observed degree sequence.
483+
"""Generates a randomized realization of a given undirected network based on the observed degree sequence.
470484
"""
471485
if g.is_directed():
486+
logger.error("molloy_reed_randomize is only implemented for undirected graphs")
472487
raise NotImplementedError('molloy_reed_randomize is only implemented for undirected graphs')
473488
# degrees are listed in order of node indices
474489
degrees = degree(g.data.edge_index[1], num_nodes=g.n, dtype=torch.int).tolist()

src/pathpyG/core/graph.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
from torch_geometric.data import Data
2020
from torch_geometric.utils import scatter, to_undirected
2121

22+
import logging
2223
from pathpyG.core.index_map import IndexMap
2324

25+
logger = logging.getLogger("root")
26+
2427

2528
class Graph:
2629
"""
@@ -60,8 +63,9 @@ def __init__(self, data: Data, mapping: Optional[IndexMap] = None):
6063
self.mapping = mapping
6164

6265
# set num_nodes property
63-
if "num_nodes" not in data and "edge_index" in data:
66+
if "num_nodes" not in data and "edge_index" in data:
6467
data.num_nodes = data.edge_index.max().item() + 1
68+
logger.debug("Inferred number of nodes from edge_index, n = %s", data.num_nodes)
6569

6670
# turn edge index tensor into EdgeIndex object
6771
if not isinstance(data.edge_index, EdgeIndex):
@@ -71,7 +75,8 @@ def __init__(self, data: Data, mapping: Optional[IndexMap] = None):
7175
data.edge_index.get_sparse_size(dim=0) != data.num_nodes
7276
or data.edge_index.get_sparse_size(dim=1) != data.num_nodes
7377
):
74-
raise Exception("sparse size of EdgeIndex should match number of nodes!")
78+
logger.error("Sparse size of edge_index does not match number of nodes, n = %s", data.num_nodes)
79+
raise ValueError("sparse size of EdgeIndex must match number of nodes!")
7580

7681
self.data = data
7782

@@ -128,6 +133,7 @@ def from_edge_index(edge_index: torch.Tensor, mapping: Optional[IndexMap] = None
128133
d = Data(edge_index=edge_index)
129134
else:
130135
if mapping is not None and mapping.num_ids() != num_nodes:
136+
logger.error("Number of node IDs in mapping must match num_nodes")
131137
raise ValueError("Number of node IDs in mapping must match num_nodes")
132138
d = Data(edge_index=edge_index, num_nodes=num_nodes)
133139
return Graph(d, mapping=mapping)
@@ -456,7 +462,8 @@ def out_degrees(self) -> Dict[str, float]:
456462
"""
457463
return self.degrees(mode="out")
458464

459-
def degrees(self, mode: str = "in", edge_attr: Any = None, return_tensor: bool = False) -> Dict[str, float]:
465+
def degrees(self, mode: str = "in", edge_attr: Any = None, return_tensor: bool = False) -> Union[Dict[str, float],
466+
torch.tensor]:
460467
"""
461468
Return (weighted) degrees of nodes.
462469
@@ -487,24 +494,6 @@ def degrees(self, mode: str = "in", edge_attr: Any = None, return_tensor: bool =
487494
else:
488495
return {str(self.mapping.to_id(i)): d[i].item() for i in range(self.n)}
489496

490-
# def weighted_outdegrees(self) -> torch.Tensor:
491-
# """
492-
# Compute the weighted outdegrees of each node in the graph.
493-
494-
# Args:
495-
# graph (Graph): pathpy graph object.
496-
497-
# Returns:
498-
# tensor: Weighted outdegrees of nodes.
499-
# """
500-
# edge_weight = getattr(self.data, "edge_weight", None)
501-
# if edge_weight is None:
502-
# edge_weight = torch.ones(self.data.num_edges, device=self.data.edge_index.device)
503-
# weighted_outdegree = scatter(
504-
# edge_weight, self.data.edge_index[0], dim=0, dim_size=self.data.num_nodes, reduce="sum"
505-
# )
506-
# return weighted_outdegree
507-
508497
def transition_probabilities(self, edge_attr: Any = None) -> torch.Tensor:
509498
"""
510499
Compute transition probabilities based on (weighted) outdegrees.

0 commit comments

Comments
 (0)