Skip to content

Commit f659505

Browse files
committed
test
1 parent 3260ae8 commit f659505

File tree

12 files changed

+471
-135
lines changed

12 files changed

+471
-135
lines changed

dhg/structure/hypergraphs/hypergraph.py

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def draw(
9696
pull_center_strength: float = 1.0,
9797
):
9898
r"""Draw the hypergraph structure.
99-
99+
100100
Args:
101101
``e_style`` (``str``): The style of hyperedges. The available styles are only ``'circle'``. Defaults to ``'circle'``.
102102
``v_label`` (``list``): The labels of vertices. Defaults to ``None``.
@@ -201,7 +201,7 @@ def from_feature_kNN(features: torch.Tensor, k: int, device: torch.device = torc
201201

202202
@staticmethod
203203
def from_graph(graph: "Graph", device: torch.device = torch.device("cpu")) -> "Hypergraph":
204-
r"""Construct the hypergraph from the graph. Each edge in the graph is treated as a hyperedge in the constructed hypergraph.
204+
r"""Construct the hypergraph from the graph. Each edge in the graph is treated as a hyperedge in the constructed hypergraph.
205205
206206
.. note::
207207
The construsted hypergraph is a 2-uniform hypergraph, and has the same number of vertices and edges/hyperedges as the graph.
@@ -263,13 +263,13 @@ def from_graph_kHop(
263263

264264
@staticmethod
265265
def _e_list_from_bigraph(bigraph: "BiGraph", U_as_vertex: bool = True) -> List[tuple]:
266-
r"""Construct hyperedges from the bipartite graph.
266+
r"""Construct hyperedges from the bipartite graph.
267267
268268
Args:
269269
``bigraph`` (``BiGraph``): The bipartite graph to construct the hypergraph.
270-
``U_as_vertex`` (``bool``, optional): If set to ``True``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
271-
will be treated as vertices and hyperedges in the constructed hypergraph, respectively.
272-
If set to ``False``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
270+
``U_as_vertex`` (``bool``, optional): If set to ``True``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
271+
will be treated as vertices and hyperedges in the constructed hypergraph, respectively.
272+
If set to ``False``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
273273
will be treated as hyperedges and vertices in the constructed hypergraph, respectively. Defaults to ``True``.
274274
"""
275275
e_list = []
@@ -289,13 +289,13 @@ def _e_list_from_bigraph(bigraph: "BiGraph", U_as_vertex: bool = True) -> List[t
289289
def from_bigraph(
290290
bigraph: "BiGraph", U_as_vertex: bool = True, device: torch.device = torch.device("cpu")
291291
) -> "Hypergraph":
292-
r"""Construct the hypergraph from the bipartite graph.
292+
r"""Construct the hypergraph from the bipartite graph.
293293
294294
Args:
295295
``bigraph`` (``BiGraph``): The bipartite graph to construct the hypergraph.
296-
``U_as_vertex`` (``bool``, optional): If set to ``True``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
297-
will be treated as vertices and hyperedges in the constructed hypergraph, respectively.
298-
If set to ``False``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
296+
``U_as_vertex`` (``bool``, optional): If set to ``True``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
297+
will be treated as vertices and hyperedges in the constructed hypergraph, respectively.
298+
If set to ``False``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
299299
will be treated as hyperedges and vertices in the constructed hypergraph, respectively. Defaults to ``True``.
300300
``device`` (``torch.device``, optional): The device to store the hypergraph. Defaults to ``torch.device('cpu')``.
301301
"""
@@ -356,7 +356,7 @@ def add_hyperedges_from_feature_kNN(self, feature: torch.Tensor, k: int, group_n
356356
self.add_hyperedges(e_list, group_name=group_name)
357357

358358
def add_hyperedges_from_graph(self, graph: "Graph", group_name: str = "main"):
359-
r"""Add hyperedges from edges in the graph. Each edge in the graph is treated as a hyperedge.
359+
r"""Add hyperedges from edges in the graph. Each edge in the graph is treated as a hyperedge.
360360
361361
Args:
362362
``graph`` (``Graph``): The graph to join the hypergraph.
@@ -385,13 +385,13 @@ def add_hyperedges_from_graph_kHop(
385385
self.add_hyperedges(e_list, group_name=group_name)
386386

387387
def add_hyperedges_from_bigraph(self, bigraph: "BiGraph", U_as_vertex: bool = False, group_name: str = "main"):
388-
r"""Add hyperedges from the bipartite graph.
388+
r"""Add hyperedges from the bipartite graph.
389389
390390
Args:
391391
``bigraph`` (``BiGraph``): The bigraph to join the hypergraph.
392-
``U_as_vertex`` (``bool``): If set to ``True``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
393-
will be treated as vertices and hyperedges in the constructed hypergraph, respectively.
394-
If set to ``False``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
392+
``U_as_vertex`` (``bool``): If set to ``True``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
393+
will be treated as vertices and hyperedges in the constructed hypergraph, respectively.
394+
If set to ``False``, vertices in set :math:`\mathcal{U}` and set :math:`\mathcal{V}`
395395
will be treated as hyperedges and vertices in the constructed hypergraph, respectively. Defaults to ``True``.
396396
``group_name`` (``str``, optional): The target hyperedge group to add these hyperedges. Defaults to the ``main`` hyperedge group.
397397
"""
@@ -624,17 +624,17 @@ def group_names(self) -> List[str]:
624624
# properties for deep learning
625625
@property
626626
def vars_for_DL(self) -> List[str]:
627-
r"""Return a name list of available variables for deep learning in the hypergraph including
627+
r"""Return a name list of available variables for deep learning in the hypergraph including
628628
629629
Sparse Matrices:
630-
630+
631631
.. math::
632632
\mathbf{H}, \mathbf{H}^\top, \mathcal{L}_{sym}, \mathcal{L}_{rw} \mathcal{L}_{HGNN},
633-
633+
634634
Sparse Diagnal Matrices:
635635
636636
.. math::
637-
\mathbf{W}_e, \mathbf{D}_v, \mathbf{D}_v^{-1}, \mathbf{D}_v^{-\frac{1}{2}}, \mathbf{D}_e, \mathbf{D}_e^{-1},
637+
\mathbf{W}_e, \mathbf{D}_v, \mathbf{D}_v^{-1}, \mathbf{D}_v^{-\frac{1}{2}}, \mathbf{D}_e, \mathbf{D}_e^{-1},
638638
639639
Vectors:
640640
@@ -670,7 +670,7 @@ def v2e_src(self) -> torch.Tensor:
670670

671671
def v2e_src_of_group(self, group_name: str) -> torch.Tensor:
672672
r"""Return the source vertex index vector :math:`\overrightarrow{v2e}_{src}` of the connections (vertices point to hyperedges) in the specified hyperedge group.
673-
673+
674674
Args:
675675
``group_name`` (``str``): The name of the specified hyperedge group.
676676
"""
@@ -685,7 +685,7 @@ def v2e_dst(self) -> torch.Tensor:
685685

686686
def v2e_dst_of_group(self, group_name: str) -> torch.Tensor:
687687
r"""Return the destination hyperedge index vector :math:`\overrightarrow{v2e}_{dst}` of the connections (vertices point to hyperedges) in the specified hyperedge group.
688-
688+
689689
Args:
690690
``group_name`` (``str``): The name of the specified hyperedge group.
691691
"""
@@ -700,7 +700,7 @@ def v2e_weight(self) -> torch.Tensor:
700700

701701
def v2e_weight_of_group(self, group_name: str) -> torch.Tensor:
702702
r"""Return the weight vector :math:`\overrightarrow{v2e}_{weight}` of the connections (vertices point to hyperedges) in the specified hyperedge group.
703-
703+
704704
Args:
705705
``group_name`` (``str``): The name of the specified hyperedge group.
706706
"""
@@ -715,7 +715,7 @@ def e2v_src(self) -> torch.Tensor:
715715

716716
def e2v_src_of_group(self, group_name: str) -> torch.Tensor:
717717
r"""Return the source hyperedge index vector :math:`\overrightarrow{e2v}_{src}` of the connections (hyperedges point to vertices) in the specified hyperedge group.
718-
718+
719719
Args:
720720
``group_name`` (``str``): The name of the specified hyperedge group.
721721
"""
@@ -730,7 +730,7 @@ def e2v_dst(self) -> torch.Tensor:
730730

731731
def e2v_dst_of_group(self, group_name: str) -> torch.Tensor:
732732
r"""Return the destination vertex index vector :math:`\overrightarrow{e2v}_{dst}` of the connections (hyperedges point to vertices) in the specified hyperedge group.
733-
733+
734734
Args:
735735
``group_name`` (``str``): The name of the specified hyperedge group.
736736
"""
@@ -745,7 +745,7 @@ def e2v_weight(self) -> torch.Tensor:
745745

746746
def e2v_weight_of_group(self, group_name: str) -> torch.Tensor:
747747
r"""Return the weight vector :math:`\overrightarrow{e2v}_{weight}` of the connections (hyperedges point to vertices) in the specified hyperedge group.
748-
748+
749749
Args:
750750
``group_name`` (``str``): The name of the specified hyperedge group.
751751
"""
@@ -1010,7 +1010,7 @@ def N_e_of_group(self, v_idx: int, group_name: str) -> torch.Tensor:
10101010
return e_indices.clone()
10111011

10121012
def N_v(self, e_idx: int) -> torch.Tensor:
1013-
r"""Return the neighbor vertices of the specified hyperedge with ``torch.Tensor`` format.
1013+
r"""Return the neighbor vertices of the specified hyperedge with ``torch.Tensor`` format.
10141014
10151015
.. note::
10161016
The ``e_idx`` must be in the range of [0, :attr:`num_e`).
@@ -1048,7 +1048,7 @@ def smoothing(self, X: torch.Tensor, L: torch.Tensor, lamb: float) -> torch.Tens
10481048
@property
10491049
def L_sym(self) -> torch.Tensor:
10501050
r"""Return the symmetric Laplacian matrix :math:`\mathcal{L}_{sym}` of the hypergraph with ``torch.sparse_coo_tensor`` format.
1051-
1051+
10521052
.. math::
10531053
\mathcal{L}_{sym} = \mathbf{I} - \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}}
10541054
"""
@@ -1064,10 +1064,10 @@ def L_sym(self) -> torch.Tensor:
10641064

10651065
def L_sym_of_group(self, group_name: str) -> torch.Tensor:
10661066
r"""Return the symmetric Laplacian matrix :math:`\mathcal{L}_{sym}` of the specified hyperedge group with ``torch.sparse_coo_tensor`` format.
1067-
1067+
10681068
.. math::
10691069
\mathcal{L}_{sym} = \mathbf{I} - \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}}
1070-
1070+
10711071
Args:
10721072
``group_name`` (``str``): The name of the specified hyperedge group.
10731073
"""
@@ -1085,7 +1085,7 @@ def L_sym_of_group(self, group_name: str) -> torch.Tensor:
10851085
@property
10861086
def L_rw(self) -> torch.Tensor:
10871087
r"""Return the random walk Laplacian matrix :math:`\mathcal{L}_{rw}` of the hypergraph with ``torch.sparse_coo_tensor`` format.
1088-
1088+
10891089
.. math::
10901090
\mathcal{L}_{rw} = \mathbf{I} - \mathbf{D}_v^{-1} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top
10911091
"""
@@ -1105,10 +1105,10 @@ def L_rw(self) -> torch.Tensor:
11051105

11061106
def L_rw_of_group(self, group_name: str) -> torch.Tensor:
11071107
r"""Return the random walk Laplacian matrix :math:`\mathcal{L}_{rw}` of the specified hyperedge group with ``torch.sparse_coo_tensor`` format.
1108-
1108+
11091109
.. math::
11101110
\mathcal{L}_{rw} = \mathbf{I} - \mathbf{D}_v^{-1} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top
1111-
1111+
11121112
Args:
11131113
``group_name`` (``str``): The name of the specified hyperedge group.
11141114
"""
@@ -1151,7 +1151,7 @@ def L_HGNN_of_group(self, group_name: str) -> torch.Tensor:
11511151
11521152
.. math::
11531153
\mathcal{L}_{HGNN} = \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}}
1154-
1154+
11551155
Args:
11561156
``group_name`` (``str``): The name of the specified hyperedge group.
11571157
"""
@@ -1172,8 +1172,8 @@ def smoothing_with_HGNN(self, X: torch.Tensor, drop_rate: float = 0.0) -> torch.
11721172
r"""Return the smoothed feature matrix with the HGNN Laplacian matrix :math:`\mathcal{L}_{HGNN}`.
11731173
11741174
.. math::
1175-
\mathbf{X} = \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}} \mathbf{X}
1176-
1175+
\mathbf{X} = \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}} \mathbf{X}
1176+
11771177
Args:
11781178
``X`` (``torch.Tensor``): The feature matrix. Size :math:`(|\mathcal{V}|, C)`.
11791179
``drop_rate`` (``float``): Dropout rate. Randomly dropout the connections in incidence matrix with probability ``drop_rate``. Default: ``0.0``.
@@ -1190,8 +1190,8 @@ def smoothing_with_HGNN_of_group(self, group_name: str, X: torch.Tensor, drop_ra
11901190
r"""Return the smoothed feature matrix with the HGNN Laplacian matrix :math:`\mathcal{L}_{HGNN}`.
11911191
11921192
.. math::
1193-
\mathbf{X} = \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}} \mathbf{X}
1194-
1193+
\mathbf{X} = \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}} \mathbf{X}
1194+
11951195
Args:
11961196
``group_name`` (``str``): The name of the specified hyperedge group.
11971197
``X`` (``torch.Tensor``): The feature matrix. Size :math:`(|\mathcal{V}|, C)`.

tests/datapipe/test_loaders.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
from dhg.datapipe import load_from_txt
44

55

6-
def test_load_from_txt():
7-
# TODO
8-
pass
6+
def test_load_from_txt(tmp_path):
7+
origin = [
8+
[0, 1, 2],
9+
[3, 4],
10+
[5, 6, 7, 8]
11+
]
12+
with open(tmp_path, 'w') as f:
13+
for ori in origin:
14+
f.write(' '.join(map(str, ori)) + '\n')
15+
data = load_from_txt(tmp_path)
16+
for ori, dat in zip(origin, data):
17+
for a, b in zip(ori, dat):
18+
assert a == b
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
import pytest
22

33
import torch
4+
from sklearn.metrics import f1_score, confusion_matrix
45
import dhg.metrics.classification as dm
56

67

78
def test_accuracy():
8-
# TODO
9-
pass
9+
y_true = torch.tensor([0, 1, 2, 0, 1, 3])
10+
y_pred = torch.tensor([0, 2, 1, 0, 2, 3])
11+
assert dm.accuracy(y_true, y_pred) == 0.5
1012

1113

1214
def test_f1_score():
13-
# TODO
14-
pass
15+
y_true = torch.tensor([0, 1, 2, 0, 1, 3])
16+
y_pred = torch.tensor([0, 2, 1, 0, 2, 3])
17+
assert dm.f1_score(y_true, y_pred, 'macro') == f1_score(y_true, y_pred, average='macro')
18+
assert dm.f1_score(y_true, y_pred, 'micro') == f1_score(y_true, y_pred, average='micro')
19+
assert dm.f1_score(y_true, y_pred, 'weighted') == f1_score(y_true, y_pred, average='weighted')
1520

1621

1722
def test_confusion_matrix():
18-
# TODO
19-
pass
23+
y_true = torch.tensor([0, 1, 2, 0, 1, 3])
24+
y_pred = torch.tensor([0, 2, 1, 0, 2, 3])
25+
assert np.all(dm.confusion_matrix(y_true, y_pred) == confusion_matrix(y_true, y_pred))

tests/metrics/test_recommender.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
import torch
4+
from sklearn.metrics import ndcg_score
45
import dhg.metrics.recommender as dm
56

67

@@ -23,5 +24,9 @@ def test_precision():
2324

2425

2526
def test_ndcg():
26-
# TODO
27-
pass
27+
y_true = torch.tensor([[0, 1, 2, 3, 4], [2, 0, 1, 4, 3]])
28+
y_score = torch.tensor([[0.8, 0.9, 0.6, 0.7, 0.4], [0.4, 0.5, 0.6, 0.7, 0.8]])
29+
assert dm.ndcg(y_true, y_score, k=2) == pytest.approx(ndcg_score(y_true, y_score, k=2))
30+
assert dm.ndcg(y_true, y_score, k=3) == pytest.approx(ndcg_score(y_true, y_score, k=3))
31+
assert dm.ndcg(y_true, y_score, k=4) == pytest.approx(ndcg_score(y_true, y_score, k=4))
32+
assert dm.ndcg(y_true, y_score, k=5) == pytest.approx(ndcg_score(y_true, y_score, k=5))

tests/metrics/test_retrieval.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import pytest
22

3+
import numpy as np
4+
from sklearn.metrics import average_precision_score, ndcg_score
35
import torch
46
import dhg.metrics.retrieval as dm
57

68

7-
def test_precision():
8-
pass
9-
10-
119
def test_recall():
1210
y_true = torch.tensor([0, 1, 0, 0, 1, 1])
1311
y_pred = torch.tensor([0.8, 0.9, 0.6, 0.7, 0.4, 0.5])
@@ -57,12 +55,30 @@ def test_ap():
5755

5856

5957
def test_map():
60-
# TODO
61-
pass
58+
y_true = torch.tensor([
59+
[True, False, True, False, True],
60+
[False, False, False, True, True],
61+
[True, True, False, True, False],
62+
[False, True, True, False, True],
63+
])
64+
y_pred = torch.tensor([
65+
[0.2, 0.8, 0.5, 0.4, 0.3],
66+
[0.8, 0.2, 0.3, 0.9, 0.4],
67+
[0.2, 0.4, 0.5, 0.9, 0.8],
68+
[0.8, 0.2, 0.9, 0.3, 0.7],
69+
])
70+
ap = []
71+
for i in range(y_true.shape[0]):
72+
ap.append(average_precision_score(y_true[i], y_pred[i]))
73+
map = np.mean(ap)
74+
assert dm.map(y_true, y_pred, method='legacy') == pytest.approx(map)
75+
6276

6377

6478
def test_ndcg():
65-
# TODO
79+
y_true = torch.tensor([0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1])
80+
y_pred = torch.tensor([0.23, 0.76, 0.01, 0.91, 0.13, 0.45, 0.12, 0.03, 0.38, 0.11, 0.03, 0.09, 0.65, 0.07, 0.12, 0.24, 0.10, 0.23, 0.46, 0.08])
81+
assert dm.ndcg(y_true, y_pred, k=5) == pytest.approx(ndcg_score(y_true.reshape(1, -1), y_pred.reshape(1, -1), k=5))
6682
pass
6783

6884

0 commit comments

Comments
 (0)