chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
import requests
|
||||
|
||||
from easygraph.utils.exception import EasyGraphError
|
||||
|
||||
|
||||
def request_text_from_url(url):
|
||||
"""
|
||||
Requests text data from the specified URL.
|
||||
|
||||
Args:
|
||||
url (str): The URL from which to request the text data.
|
||||
|
||||
Returns:
|
||||
str: The text content of the response if the request is successful.
|
||||
|
||||
Raises:
|
||||
EasyGraphError: If a connection error occurs during the request or if the HTTP response status code
|
||||
indicates a failure.
|
||||
"""
|
||||
try:
|
||||
r = requests.get(url)
|
||||
except requests.ConnectionError:
|
||||
raise EasyGraphError("Connection Error!")
|
||||
|
||||
if r.ok:
|
||||
return r.text
|
||||
else:
|
||||
raise EasyGraphError(f"Error: HTTP response {r.status_code}")
|
||||
|
||||
|
||||
class House_Committees:
|
||||
"""
|
||||
A class for loading and processing the House Committees hypergraph dataset.
|
||||
|
||||
This class fetches hyperedge, node label, node name, and label name data from predefined URLs,
|
||||
processes the data, and generates a hypergraph representation. It also provides access to various
|
||||
dataset attributes through properties and indexing.
|
||||
|
||||
Attributes:
|
||||
data_root (str): The root URL for the data. If `data_root` is provided during initialization,
|
||||
it is set to "https://"; otherwise, it is `None`.
|
||||
hyperedges_path (str): The URL of the file containing hyperedge information.
|
||||
node_labels_path (str): The URL of the file containing node label information.
|
||||
node_names_path (str): The URL of the file containing node name information.
|
||||
label_names_path (str): The URL of the file containing label name information.
|
||||
_hyperedges (list): A list of tuples representing hyperedges.
|
||||
_node_labels (list): A list of node labels.
|
||||
_label_names (list): A list of label names.
|
||||
_node_names (list): A list of node names.
|
||||
_content (dict): A dictionary containing dataset statistics and data, including the number of
|
||||
classes, vertices, edges, the edge list, and node labels.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root=None):
|
||||
"""
|
||||
Initializes a new instance of the `House_Committees` class.
|
||||
|
||||
Args:
|
||||
data_root (str, optional): The root URL for the data. If provided, it is set to "https://";
|
||||
otherwise, it is `None`. Defaults to `None`.
|
||||
"""
|
||||
self.data_root = "https://" if data_root is not None else data_root
|
||||
self.hyperedges_path = "https://gitlab.com/easy-graph/easygraph-data-house-committees/-/raw/main/hyperedges-house-committees.txt?inline=false"
|
||||
self.node_labels_path = "https://gitlab.com/easy-graph/easygraph-data-house-committees/-/raw/main/node-labels-house-committees.txt?ref_type=heads&inline=false"
|
||||
self.node_names_path = "https://gitlab.com/easy-graph/easygraph-data-house-committees/-/raw/main/node-names-house-committees.txt?ref_type=heads&inline=false"
|
||||
self.label_names_path = "https://gitlab.com/easy-graph/easygraph-data-house-committees/-/raw/main/label-names-house-committees.txt?ref_type=heads&inline=false"
|
||||
self._hyperedges = []
|
||||
self._node_labels = []
|
||||
self._label_names = []
|
||||
self._node_names = []
|
||||
self.generate_hypergraph(
|
||||
hyperedges_path=self.hyperedges_path,
|
||||
node_labels_path=self.node_labels_path,
|
||||
node_names_path=self.node_names_path,
|
||||
label_names_path=self.label_names_path,
|
||||
)
|
||||
|
||||
self._content = {
|
||||
"num_classes": len(self._label_names),
|
||||
"num_vertices": len(self._node_labels),
|
||||
"num_edges": len(self._hyperedges),
|
||||
"edge_list": self._hyperedges,
|
||||
"labels": self._node_labels,
|
||||
}
|
||||
|
||||
def process_label_txt(self, data_str, delimiter="\n", transform_fun=str):
|
||||
"""
|
||||
Processes a string containing label data into a list of transformed values.
|
||||
|
||||
Args:
|
||||
data_str (str): The input string containing label data.
|
||||
delimiter (str, optional): The delimiter used to split the input string. Defaults to "\n".
|
||||
transform_fun (callable, optional): A function used to transform each label value.
|
||||
Defaults to the `str` function.
|
||||
|
||||
Returns:
|
||||
list: A list of transformed label values.
|
||||
"""
|
||||
data_str = data_str.strip()
|
||||
data_lst = data_str.split(delimiter)
|
||||
final_lst = []
|
||||
for data in data_lst:
|
||||
data = data.strip()
|
||||
data = transform_fun(data)
|
||||
final_lst.append(data)
|
||||
return final_lst
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
"""
|
||||
Retrieves a value from the `_content` dictionary using the specified key.
|
||||
|
||||
Args:
|
||||
key (str): The key used to access the `_content` dictionary.
|
||||
|
||||
Returns:
|
||||
Any: The value corresponding to the key in the `_content` dictionary.
|
||||
"""
|
||||
return self._content[key]
|
||||
|
||||
@property
|
||||
def node_labels(self):
|
||||
"""
|
||||
Gets the list of node labels.
|
||||
|
||||
Returns:
|
||||
list: A list of node labels.
|
||||
"""
|
||||
return self._node_labels
|
||||
|
||||
@property
|
||||
def node_names(self):
|
||||
"""
|
||||
Gets the list of node names.
|
||||
|
||||
Returns:
|
||||
list: A list of node names.
|
||||
"""
|
||||
return self._node_names
|
||||
|
||||
@property
|
||||
def label_names(self):
|
||||
"""
|
||||
Gets the list of label names.
|
||||
|
||||
Returns:
|
||||
list: A list of label names.
|
||||
"""
|
||||
return self._label_names
|
||||
|
||||
@property
|
||||
def hyperedges(self):
|
||||
"""
|
||||
Gets the list of hyperedges.
|
||||
|
||||
Returns:
|
||||
list: A list of tuples representing hyperedges.
|
||||
"""
|
||||
return self._hyperedges
|
||||
|
||||
def generate_hypergraph(
|
||||
self,
|
||||
hyperedges_path=None,
|
||||
node_labels_path=None,
|
||||
node_names_path=None,
|
||||
label_names_path=None,
|
||||
):
|
||||
"""
|
||||
Generates a hypergraph by fetching and processing data from the specified URLs.
|
||||
|
||||
Args:
|
||||
hyperedges_path (str, optional): The URL of the file containing hyperedge information.
|
||||
Defaults to `None`.
|
||||
node_labels_path (str, optional): The URL of the file containing node label information.
|
||||
Defaults to `None`.
|
||||
node_names_path (str, optional): The URL of the file containing node name information.
|
||||
Defaults to `None`.
|
||||
label_names_path (str, optional): The URL of the file containing label name information.
|
||||
Defaults to `None`.
|
||||
"""
|
||||
|
||||
def fun(data):
|
||||
"""
|
||||
Converts a string to an integer and subtracts 1.
|
||||
|
||||
Args:
|
||||
data (str): The input string to be converted.
|
||||
|
||||
Returns:
|
||||
int: The converted integer value minus 1.
|
||||
"""
|
||||
data = int(data) - 1
|
||||
return data
|
||||
|
||||
hyperedges_info = request_text_from_url(hyperedges_path)
|
||||
hyperedges_info = hyperedges_info.strip()
|
||||
hyperedges_lst = hyperedges_info.split("\n")
|
||||
for hyperedge in hyperedges_lst:
|
||||
hyperedge = hyperedge.strip()
|
||||
hyperedge = [int(i) - 1 for i in hyperedge.split(",")]
|
||||
self._hyperedges.append(tuple(hyperedge))
|
||||
# print(self.hyperedges)
|
||||
|
||||
node_labels_info = request_text_from_url(node_labels_path)
|
||||
|
||||
process_node_labels_info = self.process_label_txt(
|
||||
node_labels_info, transform_fun=fun
|
||||
)
|
||||
self._node_labels = process_node_labels_info
|
||||
# print("process_node_labels_info:", process_node_labels_info)
|
||||
node_names_info = request_text_from_url(node_names_path)
|
||||
process_node_names_info = self.process_label_txt(node_names_info)
|
||||
self._node_names = process_node_names_info
|
||||
# print("process_node_names_info:", process_node_names_info)
|
||||
label_names_info = request_text_from_url(label_names_path)
|
||||
process_label_names_info = self.process_label_txt(label_names_info)
|
||||
self._label_names = process_label_names_info
|
||||
@@ -0,0 +1,82 @@
|
||||
from typing import Optional
|
||||
|
||||
from easygraph.datapipe import load_from_pickle
|
||||
from easygraph.datapipe import to_long_tensor
|
||||
from easygraph.datapipe import to_tensor
|
||||
from easygraph.datasets.hypergraph.hypergraph_dataset_base import BaseData
|
||||
|
||||
|
||||
class YelpRestaurant(BaseData):
|
||||
r"""The Yelp-Restaurant dataset is a restaurant-review network dataset for node classification task.
|
||||
|
||||
More details see the DHG or `YOU ARE ALLSET: A MULTISET LEARNING FRAMEWORK FOR HYPERGRAPH NEURAL NETWORKS <https://openreview.net/pdf?id=hpBTIv2uy_E>`_ paper.
|
||||
|
||||
The content of the Yelp-Restaurant dataset includes the following:
|
||||
|
||||
- ``num_classes``: The number of classes: :math:`11`.
|
||||
- ``num_vertices``: The number of vertices: :math:`50,758`.
|
||||
- ``num_edges``: The number of edges: :math:`679,302`.
|
||||
- ``dim_features``: The dimension of features: :math:`1,862`.
|
||||
- ``features``: The vertex feature matrix. ``torch.Tensor`` with size :math:`(50,758 \times 1,862)`.
|
||||
- ``edge_list``: The edge list. ``List`` with length :math:`679,302`.
|
||||
- ``labels``: The label list. ``torch.LongTensor`` with size :math:`(50,758, )`.
|
||||
- ``state``: The state list. ``torch.LongTensor`` with size :math:`(50,758, )`.
|
||||
- ``city``: The city list. ``torch.LongTensor`` with size :math:`(50,758, )`.
|
||||
|
||||
Args:
|
||||
``data_root`` (``str``, optional): The ``data_root`` has stored the data. If set to ``None``, this function will auto-download from server and save into the default direction ``~/.dhg/datasets/``. Defaults to ``None``.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root: Optional[str] = None) -> None:
|
||||
super().__init__("yelp_restaurant", data_root)
|
||||
self._content = {
|
||||
"num_classes": 11,
|
||||
"num_vertices": 50758,
|
||||
"num_edges": 679302,
|
||||
"dim_features": 1862,
|
||||
"features": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "features.pkl",
|
||||
"md5": "cedc4443884477c2e626025411c44cd7",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [
|
||||
to_tensor,
|
||||
],
|
||||
},
|
||||
"edge_list": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "edge_list.pkl",
|
||||
"md5": "4b26eecaa22305dd10edcd6372eb49da",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
},
|
||||
"labels": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "labels.pkl",
|
||||
"md5": "1cdc1ed9fb1f57b2accaa42db214d4ef",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
"state": {
|
||||
"upon": [
|
||||
{"filename": "state.pkl", "md5": "eef3b835fad37409f29ad36539296b57"}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
"city": {
|
||||
"upon": [
|
||||
{"filename": "city.pkl", "md5": "8302b167262b23067698e865cacd0b17"}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
from .cat_edge_Cooking import *
|
||||
from .coauthorship import *
|
||||
from .cocitation import *
|
||||
from .contact_primary_school import *
|
||||
from .House_Committees import *
|
||||
from .mathoverflow_answers import *
|
||||
from .senate_committees import *
|
||||
from .trivago_clicks import *
|
||||
from .walmart_trips import *
|
||||
from .Yelp import *
|
||||
@@ -0,0 +1,14 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def get_eg_cache_root():
|
||||
root = Path.home() / Path(".easygraph/")
|
||||
root.mkdir(parents=True, exist_ok=True)
|
||||
return root
|
||||
|
||||
|
||||
CACHE_ROOT = get_eg_cache_root()
|
||||
DATASETS_ROOT = CACHE_ROOT / "datasets"
|
||||
|
||||
REMOTE_ROOT = "https://download.moon-lab.tech:28501/"
|
||||
REMOTE_DATASETS_ROOT = REMOTE_ROOT + "datasets/"
|
||||
@@ -0,0 +1,104 @@
|
||||
import requests
|
||||
|
||||
from easygraph.utils.exception import EasyGraphError
|
||||
|
||||
|
||||
def request_text_from_url(url):
|
||||
try:
|
||||
r = requests.get(url)
|
||||
except requests.ConnectionError:
|
||||
raise EasyGraphError("Connection Error!")
|
||||
|
||||
if r.ok:
|
||||
return r.text
|
||||
else:
|
||||
raise EasyGraphError(f"Error: HTTP response {r.status_code}")
|
||||
|
||||
|
||||
class cat_edge_Cooking:
|
||||
def __init__(self, data_root=None):
|
||||
self.data_root = "https://" if data_root is not None else data_root
|
||||
self.hyperedges_path = "https://gitlab.com/easy-graph/easygraph-data-cat-edge-cooking/-/raw/main/hyperedges.txt?inline=false"
|
||||
self.edge_labels_path = "https://gitlab.com/easy-graph/easygraph-data-cat-edge-cooking/-/raw/main/hyperedge-labels.txt?ref_type=heads&inline=false"
|
||||
self.node_names_path = "https://gitlab.com/easy-graph/easygraph-data-cat-edge-cooking/-/raw/main/main/node-labels.txt?ref_type=heads&inline=false"
|
||||
self.label_names_path = "https://gitlab.com/easy-graph/easygraph-data-cat-edge-cooking/-/raw/main/hyperedge-label-identities.txt?ref_type=heads&inline=false"
|
||||
# self.hyperedges_path = []
|
||||
# self.edge_labels_path = []
|
||||
# self.node_names_path = []
|
||||
# self.label_names_path = []
|
||||
self.generate_hypergraph(
|
||||
hyperedges_path=self.hyperedges_path,
|
||||
edge_labels_path=self.edge_labels_path,
|
||||
node_names_path=self.node_names_path,
|
||||
label_names_path=self.label_names_path,
|
||||
)
|
||||
self._content = {
|
||||
"num_classes": len(self._label_names),
|
||||
"num_vertices": len(self._node_labels),
|
||||
"num_edges": len(self._hyperedges),
|
||||
"edge_list": self._hyperedges,
|
||||
"labels": self._node_labels,
|
||||
}
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
return self._content[key]
|
||||
|
||||
def process_label_txt(self, data_str, delimiter="\n", transform_fun=str):
|
||||
data_str = data_str.strip()
|
||||
data_lst = data_str.split(delimiter)
|
||||
final_lst = []
|
||||
for data in data_lst:
|
||||
data = data.strip()
|
||||
data = transform_fun(data)
|
||||
final_lst.append(data)
|
||||
return final_lst
|
||||
|
||||
@property
|
||||
def edge_labels(self):
|
||||
return self._edge_labels
|
||||
|
||||
@property
|
||||
def node_names(self):
|
||||
return self._node_names
|
||||
|
||||
@property
|
||||
def label_names(self):
|
||||
return self._label_names
|
||||
|
||||
@property
|
||||
def hyperedges(self):
|
||||
return self._hyperedges
|
||||
|
||||
def generate_hypergraph(
|
||||
self,
|
||||
hyperedges_path=None,
|
||||
node_labels_path=None,
|
||||
node_names_path=None,
|
||||
label_names_path=None,
|
||||
):
|
||||
def fun(data):
|
||||
data = int(data) - 1
|
||||
return data
|
||||
|
||||
hyperedges_info = request_text_from_url(hyperedges_path)
|
||||
hyperedges_info = hyperedges_info.strip()
|
||||
hyperedges_lst = hyperedges_info.split("\n")
|
||||
for hyperedge in hyperedges_lst:
|
||||
hyperedge = hyperedge.strip()
|
||||
hyperedge = [int(i) - 1 for i in hyperedge.split(" ")]
|
||||
self._hyperedges.append(tuple(hyperedge))
|
||||
# print(self.hyperedges)
|
||||
|
||||
edge_labels_info = request_text_from_url(self.edge_labels_path)
|
||||
process_node_labels_info = self.process_label_txt(
|
||||
node_labels_info, transform_fun=fun
|
||||
)
|
||||
self._edge_labels = process_edge_labels_info()
|
||||
|
||||
node_names_info = request_text_from_url(node_names_path)
|
||||
process_node_names_info = self.process_label_txt(node_names_info)
|
||||
self._node_names = process_node_names_info
|
||||
|
||||
label_names_info = request_text_from_url(label_names_path)
|
||||
process_label_names_info = self.process_label_txt(label_names_info)
|
||||
self._label_names = process_label_names_info
|
||||
@@ -0,0 +1,192 @@
|
||||
from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
from easygraph.datapipe import load_from_pickle
|
||||
from easygraph.datapipe import norm_ft
|
||||
from easygraph.datapipe import to_bool_tensor
|
||||
from easygraph.datapipe import to_long_tensor
|
||||
from easygraph.datapipe import to_tensor
|
||||
from easygraph.datasets.hypergraph.hypergraph_dataset_base import BaseData
|
||||
|
||||
|
||||
__all__ = ["CoauthorshipCora", "CoauthorshipDBLP"]
|
||||
|
||||
|
||||
class CoauthorshipCora(BaseData):
|
||||
r"""The Co-authorship Cora dataset is a citation network dataset for vertex classification task.
|
||||
More details see the `HyperGCN <https://papers.nips.cc/paper/2019/file/1efa39bcaec6f3900149160693694536-Paper.pdf>`_ paper.
|
||||
|
||||
The content of the Co-authorship Cora dataset includes the following:
|
||||
|
||||
- ``num_classes``: The number of classes: :math:`7`.
|
||||
- ``num_vertices``: The number of vertices: :math:`2,708`.
|
||||
- ``num_edges``: The number of edges: :math:`1,072`.
|
||||
- ``dim_features``: The dimension of features: :math:`1,433`.
|
||||
- ``features``: The vertex feature matrix. ``torch.Tensor`` with size :math:`(2,708 \times 1,433)`.
|
||||
- ``edge_list``: The edge list. ``List`` with length :math:`1,072`.
|
||||
- ``labels``: The label list. ``torch.LongTensor`` with size :math:`(2,708, )`.
|
||||
- ``train_mask``: The train mask. ``torch.BoolTensor`` with size :math:`(2,708, )`.
|
||||
- ``val_mask``: The validation mask. ``torch.BoolTensor`` with size :math:`(2,708, )`.
|
||||
- ``test_mask``: The test mask. ``torch.BoolTensor`` with size :math:`(2,708, )`.
|
||||
|
||||
Args:
|
||||
``data_root`` (``str``, optional): The ``data_root`` has stored the data. If set to ``None``, this function will auto-download from server and save into the default direction ``~/.dhg/datasets/``. Defaults to ``None``.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root: Optional[str] = None) -> None:
|
||||
super().__init__("coauthorship_cora", data_root)
|
||||
self._content = {
|
||||
"num_classes": 7,
|
||||
"num_vertices": 2708,
|
||||
"num_edges": 1072,
|
||||
"dim_features": 1433,
|
||||
"features": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "features.pkl",
|
||||
"md5": "14257c0e24b4eb741b469a351e524785",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_tensor, partial(norm_ft, ord=1)],
|
||||
},
|
||||
"edge_list": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "edge_list.pkl",
|
||||
"md5": "a17ff337f1b9099f5a9d4d670674e146",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
},
|
||||
"labels": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "labels.pkl",
|
||||
"md5": "c8d11c452e0be69f79a47dd839279117",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
"train_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "train_mask.pkl",
|
||||
"md5": "111db6c6f986be2908378df7bdca7a9b",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"val_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "val_mask.pkl",
|
||||
"md5": "ffab1055193ffb2fe74822bb575d332a",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"test_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "test_mask.pkl",
|
||||
"md5": "ffab1055193ffb2fe74822bb575d332a",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class CoauthorshipDBLP(BaseData):
|
||||
r"""The Co-authorship DBLP dataset is a citation network dataset for vertex classification task.
|
||||
More details see the `HyperGCN <https://papers.nips.cc/paper/2019/file/1efa39bcaec6f3900149160693694536-Paper.pdf>`_ paper.
|
||||
|
||||
The content of the Co-authorship DBLP dataset includes the following:
|
||||
|
||||
- ``num_classes``: The number of classes: :math:`6`.
|
||||
- ``num_vertices``: The number of vertices: :math:`41,302`.
|
||||
- ``num_edges``: The number of edges: :math:`22,363`.
|
||||
- ``dim_features``: The dimension of features: :math:`1,425`.
|
||||
- ``features``: The vertex feature matrix. ``torch.Tensor`` with size :math:`(41,302 \times 1,425)`.
|
||||
- ``edge_list``: The edge list. ``List`` with length :math:`22,363`.
|
||||
- ``labels``: The label list. ``torch.LongTensor`` with size :math:`(41,302, )`.
|
||||
- ``train_mask``: The train mask. ``torch.BoolTensor`` with size :math:`(41,302, )`.
|
||||
- ``val_mask``: The validation mask. ``torch.BoolTensor`` with size :math:`(41,302, )`.
|
||||
- ``test_mask``: The test mask. ``torch.BoolTensor`` with size :math:`(41,302, )`.
|
||||
|
||||
Args:
|
||||
``data_root`` (``str``, optional): The ``data_root`` has stored the data. If set to ``None``, this function will auto-download from server and save into the default direction ``~/.dhg/datasets/``. Defaults to None.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root: Optional[str] = None) -> None:
|
||||
super().__init__("coauthorship_dblp", data_root)
|
||||
self._content = {
|
||||
"num_classes": 6,
|
||||
"num_vertices": 41302,
|
||||
"num_edges": 22363,
|
||||
"dim_features": 1425,
|
||||
"features": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "features.pkl",
|
||||
"md5": "b78fd31b2586d1e19a40b3f6cd9cc2e7",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_tensor, partial(norm_ft, ord=1)],
|
||||
},
|
||||
"edge_list": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "edge_list.pkl",
|
||||
"md5": "c6bf5f9f3b9683bcc9b7bcc9eb8707d8",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
},
|
||||
"labels": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "labels.pkl",
|
||||
"md5": "2e7a792ea018028d582af8f02f2058ca",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
"train_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "train_mask.pkl",
|
||||
"md5": "a842b795c7cac4c2f98a56cf599bc1de",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"val_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "val_mask.pkl",
|
||||
"md5": "2ec4b7df7c5e6b355067a22c391ad578",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"test_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "test_mask.pkl",
|
||||
"md5": "2ec4b7df7c5e6b355067a22c391ad578",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
from functools import partial
|
||||
from typing import Optional
|
||||
|
||||
from easygraph.datapipe import load_from_pickle
|
||||
from easygraph.datapipe import norm_ft
|
||||
from easygraph.datapipe import to_bool_tensor
|
||||
from easygraph.datapipe import to_long_tensor
|
||||
from easygraph.datapipe import to_tensor
|
||||
from easygraph.datasets.hypergraph.hypergraph_dataset_base import BaseData
|
||||
|
||||
|
||||
class CocitationCora(BaseData):
|
||||
r"""The Co-citation Cora dataset is a citation network dataset for vertex classification task.
|
||||
More details see the `HyperGCN <https://papers.nips.cc/paper/2019/file/1efa39bcaec6f3900149160693694536-Paper.pdf>`_ paper.
|
||||
|
||||
The content of the Co-citation Cora dataset includes the following:
|
||||
|
||||
- ``num_classes``: The number of classes: :math:`7`.
|
||||
- ``num_vertices``: The number of vertices: :math:`2,708`.
|
||||
- ``num_edges``: The number of edges: :math:`1,579`.
|
||||
- ``dim_features``: The dimension of features: :math:`1,433`.
|
||||
- ``features``: The vertex feature matrix. ``torch.Tensor`` with size :math:`(2,708 \times 1,433)`.
|
||||
- ``edge_list``: The edge list. ``List`` with length :math:`1,579`.
|
||||
- ``labels``: The label list. ``torch.LongTensor`` with size :math:`(2,708, )`.
|
||||
- ``train_mask``: The train mask. ``torch.BoolTensor`` with size :math:`(2,708, )`.
|
||||
- ``val_mask``: The validation mask. ``torch.BoolTensor`` with size :math:`(2,708, )`.
|
||||
- ``test_mask``: The test mask. ``torch.BoolTensor`` with size :math:`(2,708, )`.
|
||||
|
||||
Args:
|
||||
``data_root`` (``str``, optional): The ``data_root`` has stored the data. If set to ``None``, this function will auto-download from server and save into the default direction ``~/.dhg/datasets/``. Defaults to ``None``.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root: Optional[str] = None) -> None:
|
||||
super().__init__("cocitation_cora", data_root)
|
||||
self._content = {
|
||||
"num_classes": 7,
|
||||
"num_vertices": 2708,
|
||||
"num_edges": 1579,
|
||||
"dim_features": 1433,
|
||||
"features": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "features.pkl",
|
||||
"md5": "14257c0e24b4eb741b469a351e524785",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_tensor, partial(norm_ft, ord=1)],
|
||||
},
|
||||
"edge_list": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "edge_list.pkl",
|
||||
"md5": "e43d1321880c8ecb2260d8fb7effd9ea",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
},
|
||||
"labels": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "labels.pkl",
|
||||
"md5": "c8d11c452e0be69f79a47dd839279117",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
"train_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "train_mask.pkl",
|
||||
"md5": "111db6c6f986be2908378df7bdca7a9b",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"val_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "val_mask.pkl",
|
||||
"md5": "ffab1055193ffb2fe74822bb575d332a",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"test_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "test_mask.pkl",
|
||||
"md5": "ffab1055193ffb2fe74822bb575d332a",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class CocitationCiteseer(BaseData):
|
||||
r"""The Co-citation Citeseer dataset is a citation network dataset for vertex classification task.
|
||||
More details see the `HyperGCN <https://papers.nips.cc/paper/2019/file/1efa39bcaec6f3900149160693694536-Paper.pdf>`_ paper.
|
||||
|
||||
The content of the Co-citation Citaseer dataset includes the following:
|
||||
|
||||
- ``num_classes``: The number of classes: :math:`6`.
|
||||
- ``num_vertices``: The number of vertices: :math:`3,312`.
|
||||
- ``num_edges``: The number of edges: :math:`1,079`.
|
||||
- ``dim_features``: The dimension of features: :math:`3,703`.
|
||||
- ``features``: The vertex feature matrix. ``torch.Tensor`` with size :math:`(3,312 \times 3,703)`.
|
||||
- ``edge_list``: The edge list. ``List`` with length :math:`1,079`.
|
||||
- ``labels``: The label list. ``torch.LongTensor`` with size :math:`(3,312, )`.
|
||||
- ``train_mask``: The train mask. ``torch.BoolTensor`` with size :math:`(3,312, )`.
|
||||
- ``val_mask``: The validation mask. ``torch.BoolTensor`` with size :math:`(3,312, )`.
|
||||
- ``test_mask``: The test mask. ``torch.BoolTensor`` with size :math:`(3,312, )`.
|
||||
|
||||
Args:
|
||||
``data_root`` (``str``, optional): The ``data_root`` has stored the data. If set to ``None``, this function will auto-download from server and save into the default direction ``~/.dhg/datasets/``. Defaults to ``None``.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root: Optional[str] = None) -> None:
|
||||
super().__init__("cocitation_citeseer", data_root)
|
||||
self._content = {
|
||||
"num_classes": 6,
|
||||
"num_vertices": 3312,
|
||||
"num_edges": 1079,
|
||||
"dim_features": 3703,
|
||||
"features": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "features.pkl",
|
||||
"md5": "1ee0dc89e0d5f5ac9187b55a407683e8",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_tensor, partial(norm_ft, ord=1)],
|
||||
},
|
||||
"edge_list": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "edge_list.pkl",
|
||||
"md5": "6687b2e96159c534a424253f536b49ae",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
},
|
||||
"labels": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "labels.pkl",
|
||||
"md5": "71069f78e83fa85dd6a4b9b6570447c2",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
"train_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "train_mask.pkl",
|
||||
"md5": "3b831318fc3d3e588bead5ba469fe38f",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"val_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "val_mask.pkl",
|
||||
"md5": "c22eb5b7493908042c7e039c8bb5a82e",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"test_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "test_mask.pkl",
|
||||
"md5": "c22eb5b7493908042c7e039c8bb5a82e",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class CocitationPubmed(BaseData):
|
||||
r"""The Co-citation PubMed dataset is a citation network dataset for vertex classification task.
|
||||
More details see the `HyperGCN <https://papers.nips.cc/paper/2019/file/1efa39bcaec6f3900149160693694536-Paper.pdf>`_ paper.
|
||||
|
||||
The content of the Co-citation PubMed dataset includes the following:
|
||||
|
||||
- ``num_classes``: The number of classes: :math:`3`.
|
||||
- ``num_vertices``: The number of vertices: :math:`19,717`.
|
||||
- ``num_edges``: The number of edges: :math:`7,963`.
|
||||
- ``dim_features``: The dimension of features: :math:`500`.
|
||||
- ``features``: The vertex feature matrix. ``torch.Tensor`` with size :math:`(19,717 \times 500)`.
|
||||
- ``edge_list``: The edge list. ``List`` with length :math:`7,963`.
|
||||
- ``labels``: The label list. ``torch.LongTensor`` with size :math:`(19,717, )`.
|
||||
- ``train_mask``: The train mask. ``torch.BoolTensor`` with size :math:`(19,717, )`.
|
||||
- ``val_mask``: The validation mask. ``torch.BoolTensor`` with size :math:`(19,717, )`.
|
||||
- ``test_mask``: The test mask. ``torch.BoolTensor`` with size :math:`(19,717, )`.
|
||||
|
||||
Args:
|
||||
``data_root`` (``str``, optional): The ``data_root`` has stored the data. If set to ``None``, this function will auto-download from server and save into the default direction ``~/.dhg/datasets/``. Defaults to ``None``.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root: Optional[str] = None) -> None:
|
||||
super().__init__("cocitation_pubmed", data_root)
|
||||
self._content = {
|
||||
"num_classes": 3,
|
||||
"num_vertices": 19717,
|
||||
"num_edges": 7963,
|
||||
"dim_features": 500,
|
||||
"features": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "features.pkl",
|
||||
"md5": "f89502c432ca451156a8235c5efc034e",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_tensor, partial(norm_ft, ord=1)],
|
||||
},
|
||||
"edge_list": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "edge_list.pkl",
|
||||
"md5": "c5fbedf63e5be527f200e8c4e0391b00",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
},
|
||||
"labels": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "labels.pkl",
|
||||
"md5": "c039f778409a15f9b2ceefacad9c2202",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
"train_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "train_mask.pkl",
|
||||
"md5": "81b422937f3adccd89a334d7093b67d7",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"val_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "val_mask.pkl",
|
||||
"md5": "10717940ddbfa3e4f6c0b148bb394f79",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"test_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "test_mask.pkl",
|
||||
"md5": "10717940ddbfa3e4f6c0b148bb394f79",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
import requests
|
||||
|
||||
from easygraph.utils.exception import EasyGraphError
|
||||
|
||||
|
||||
def request_text_from_url(url):
|
||||
"""Requests text data from the specified URL.
|
||||
|
||||
Args:
|
||||
url (str): The URL from which to request data.
|
||||
|
||||
Returns:
|
||||
str: The text content of the response if the request is successful.
|
||||
|
||||
Raises:
|
||||
EasyGraphError: If a connection error occurs or the HTTP response status code indicates failure.
|
||||
"""
|
||||
try:
|
||||
r = requests.get(url)
|
||||
except requests.ConnectionError:
|
||||
raise EasyGraphError("Connection Error!")
|
||||
|
||||
if r.ok:
|
||||
return r.text
|
||||
else:
|
||||
raise EasyGraphError(f"Error: HTTP response {r.status_code}")
|
||||
|
||||
|
||||
class contact_primary_school:
|
||||
"""A class for loading and processing the primary school contact network hypergraph dataset.
|
||||
|
||||
This class loads hyperedge, node label, and label name data from specified URLs and generates a hypergraph.
|
||||
|
||||
Attributes:
|
||||
data_root (str): The root URL for the data. If not provided, it is set to None.
|
||||
hyperedges_path (str): The URL for the hyperedge data.
|
||||
node_labels_path (str): The URL for the node label data.
|
||||
label_names_path (str): The URL for the label name data.
|
||||
_hyperedges (list): A list storing hyperedges.
|
||||
_node_labels (list): A list storing node labels.
|
||||
_label_names (list): A list storing label names.
|
||||
_node_names (list): A list storing node names (currently unused).
|
||||
_content (dict): A dictionary containing dataset statistics and data.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root=None):
|
||||
"""Initializes an instance of the contact_primary_school class.
|
||||
|
||||
Args:
|
||||
data_root (str, optional): The root URL for the data. Defaults to None.
|
||||
"""
|
||||
self.data_root = "https://" if data_root is not None else data_root
|
||||
self.hyperedges_path = "https://gitlab.com/easy-graph/easygraph-data-contact-primary-school/-/raw/main/hyperedges-contact-primary-school.txt?inline=false"
|
||||
self.node_labels_path = "https://gitlab.com/easy-graph/easygraph-data-contact-primary-school/-/raw/main/node-labels-contact-primary-school.txt?ref_type=heads&inline=false"
|
||||
# self.node_names_path = "https://gitlab.com/easy-graph/easygraph-data-house-committees/-/raw/main/node-names-house-committees.txt?ref_type=heads&inline=false"
|
||||
self.label_names_path = "https://gitlab.com/easy-graph/easygraph-data-contact-primary-school/-/raw/main/label-names-contact-primary-school.txt?ref_type=heads&inline=false"
|
||||
self._hyperedges = []
|
||||
self._node_labels = []
|
||||
self._label_names = []
|
||||
self._node_names = []
|
||||
self.generate_hypergraph(
|
||||
hyperedges_path=self.hyperedges_path,
|
||||
node_labels_path=self.node_labels_path,
|
||||
# node_names_path=self.node_names_path,
|
||||
label_names_path=self.label_names_path,
|
||||
)
|
||||
self._content = {
|
||||
"num_classes": len(self._label_names),
|
||||
"num_vertices": len(self._node_labels),
|
||||
"num_edges": len(self._hyperedges),
|
||||
"edge_list": self._hyperedges,
|
||||
"labels": self._node_labels,
|
||||
}
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
"""Accesses data in the _content dictionary by key.
|
||||
|
||||
Args:
|
||||
key (str): The key of the data to access.
|
||||
|
||||
Returns:
|
||||
Any: The value corresponding to the key in the _content dictionary.
|
||||
"""
|
||||
return self._content[key]
|
||||
|
||||
def process_label_txt(self, data_str, delimiter="\n", transform_fun=str):
|
||||
"""Processes label data read from a text file.
|
||||
|
||||
Args:
|
||||
data_str (str): A string containing label data.
|
||||
delimiter (str, optional): The delimiter used to split the string. Defaults to "\n".
|
||||
transform_fun (callable, optional): A function used to transform each label. Defaults to str.
|
||||
|
||||
Returns:
|
||||
list: A list of processed labels.
|
||||
"""
|
||||
data_str = data_str.strip()
|
||||
data_lst = data_str.split(delimiter)
|
||||
final_lst = []
|
||||
for data in data_lst:
|
||||
data = data.strip()
|
||||
data = transform_fun(data)
|
||||
final_lst.append(data)
|
||||
return final_lst
|
||||
|
||||
@property
|
||||
def node_labels(self):
|
||||
"""Gets the list of node labels.
|
||||
|
||||
Returns:
|
||||
list: A list of node labels.
|
||||
"""
|
||||
return self._node_labels
|
||||
|
||||
"""
|
||||
@property
|
||||
def node_names(self):
|
||||
return self._node_names
|
||||
"""
|
||||
|
||||
@property
|
||||
def label_names(self):
|
||||
"""Gets the list of label names.
|
||||
|
||||
Returns:
|
||||
list: A list of label names.
|
||||
"""
|
||||
return self._label_names
|
||||
|
||||
@property
|
||||
def hyperedges(self):
|
||||
"""Gets the list of hyperedges.
|
||||
|
||||
Returns:
|
||||
list: A list of hyperedges.
|
||||
"""
|
||||
return self._hyperedges
|
||||
|
||||
def generate_hypergraph(
|
||||
self,
|
||||
hyperedges_path=None,
|
||||
node_labels_path=None,
|
||||
# node_names_path=None,
|
||||
label_names_path=None,
|
||||
):
|
||||
"""Generates hypergraph data from specified URLs.
|
||||
|
||||
Args:
|
||||
hyperedges_path (str, optional): The URL for the hyperedge data. Defaults to None.
|
||||
node_labels_path (str, optional): The URL for the node label data. Defaults to None.
|
||||
label_names_path (str, optional): The URL for the label name data. Defaults to None.
|
||||
"""
|
||||
|
||||
def fun(data):
|
||||
"""Converts the input data to an integer and subtracts 1.
|
||||
|
||||
Args:
|
||||
data (str): The input string data.
|
||||
|
||||
Returns:
|
||||
int: The converted integer data.
|
||||
"""
|
||||
data = int(data) - 1
|
||||
return data
|
||||
|
||||
hyperedges_info = request_text_from_url(hyperedges_path)
|
||||
hyperedges_info = hyperedges_info.strip()
|
||||
hyperedges_lst = hyperedges_info.split("\n")
|
||||
for hyperedge in hyperedges_lst:
|
||||
hyperedge = hyperedge.strip()
|
||||
hyperedge = [int(i) - 1 for i in hyperedge.split(",")]
|
||||
self._hyperedges.append(tuple(hyperedge))
|
||||
# print(self.hyperedges)
|
||||
|
||||
node_labels_info = request_text_from_url(node_labels_path)
|
||||
|
||||
process_node_labels_info = self.process_label_txt(
|
||||
node_labels_info, transform_fun=fun
|
||||
)
|
||||
self._node_labels = process_node_labels_info
|
||||
label_names_info = request_text_from_url(label_names_path)
|
||||
process_label_names_info = self.process_label_txt(label_names_info)
|
||||
self._label_names = process_label_names_info
|
||||
@@ -0,0 +1,85 @@
|
||||
from typing import Optional
|
||||
|
||||
from easygraph.datapipe import load_from_pickle
|
||||
from easygraph.datapipe import to_bool_tensor
|
||||
from easygraph.datapipe import to_long_tensor
|
||||
from easygraph.datasets.hypergraph.hypergraph_dataset_base import BaseData
|
||||
|
||||
|
||||
class Cooking200(BaseData):
|
||||
r"""The Cooking 200 dataset is collected from `Yummly.com <https://www.yummly.com/>`_ for vertex classification task.
|
||||
It is a hypergraph dataset, in which vertex denotes the dish and hyperedge denotes
|
||||
the ingredient. Each dish is also associated with category information, which indicates the dish's cuisine like
|
||||
Chinese, Japanese, French, and Russian.
|
||||
|
||||
The content of the Cooking200 dataset includes the following:
|
||||
|
||||
- ``num_classes``: The number of classes: :math:`20`.
|
||||
- ``num_vertices``: The number of vertices: :math:`7,403`.
|
||||
- ``num_edges``: The number of edges: :math:`2,755`.
|
||||
- ``edge_list``: The edge list. ``List`` with length :math:`(2,755)`.
|
||||
- ``labels``: The label list. ``torch.LongTensor`` with size :math:`(7,403)`.
|
||||
- ``train_mask``: The train mask. ``torch.BoolTensor`` with size :math:`(7,403)`.
|
||||
- ``val_mask``: The validation mask. ``torch.BoolTensor`` with size :math:`(7,403)`.
|
||||
- ``test_mask``: The test mask. ``torch.BoolTensor`` with size :math:`(7,403)`.
|
||||
|
||||
Args:
|
||||
``data_root`` (``str``, optional): The ``data_root`` has stored the data. If set to ``None``, this function will auto-download from server and save into the default direction ``~/.dhg/datasets/``. Defaults to ``None``.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root: Optional[str] = None) -> None:
|
||||
super().__init__("cooking_200", data_root)
|
||||
self._content = {
|
||||
"num_classes": 20,
|
||||
"num_vertices": 7403,
|
||||
"num_edges": 2755,
|
||||
"edge_list": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "edge_list.pkl",
|
||||
"md5": "2cd32e13dd4e33576c43936542975220",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
},
|
||||
"labels": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "labels.pkl",
|
||||
"md5": "f1f3c0399c9c28547088f44e0bfd5c81",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_long_tensor],
|
||||
},
|
||||
"train_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "train_mask.pkl",
|
||||
"md5": "66ea36bae024aaaed289e1998fe894bd",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"val_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "val_mask.pkl",
|
||||
"md5": "6c0d3d8b752e3955c64788cc65dcd018",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
"test_mask": {
|
||||
"upon": [
|
||||
{
|
||||
"filename": "test_mask.pkl",
|
||||
"md5": "0e1564904551ba493e1f8a09d103461e",
|
||||
}
|
||||
],
|
||||
"loader": load_from_pickle,
|
||||
"preprocess": [to_bool_tensor],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
|
||||
from easygraph.datapipe import compose_pipes
|
||||
from easygraph.datasets.hypergraph._global import DATASETS_ROOT
|
||||
from easygraph.datasets.hypergraph._global import REMOTE_DATASETS_ROOT
|
||||
from easygraph.datasets.utils import download_and_check
|
||||
|
||||
|
||||
class BaseData:
|
||||
r"""The Base Class of all datasets.
|
||||
|
||||
::
|
||||
|
||||
self._content = {
|
||||
'item': {
|
||||
'upon': [
|
||||
{'filename': 'part1.pkl', 'md5': 'xxxxx',},
|
||||
{'filename': 'part2.pkl', 'md5': 'xxxxx',},
|
||||
],
|
||||
'loader': loader_function,
|
||||
'preprocess': [datapipe1, datapipe2],
|
||||
},
|
||||
...
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name: str, data_root=None):
|
||||
# configure the data local/remote root
|
||||
self.name = name
|
||||
if data_root is None:
|
||||
self.data_root = DATASETS_ROOT / name
|
||||
else:
|
||||
self.data_root = Path(data_root) / name
|
||||
self.remote_root = REMOTE_DATASETS_ROOT + name + "/"
|
||||
# init
|
||||
self._content = {}
|
||||
self._raw = {}
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"This is {self.name} dataset:\n"
|
||||
+ "\n".join(f" -> {k}" for k in self.content)
|
||||
+ "\nPlease try `data['name']` to get the specified data."
|
||||
)
|
||||
|
||||
@property
|
||||
def content(self):
|
||||
r"""Return the content of the dataset."""
|
||||
return list(self._content.keys())
|
||||
|
||||
def needs_to_load(self, item_name: str) -> bool:
|
||||
r"""Return whether the ``item_name`` of the dataset needs to be loaded.
|
||||
|
||||
Args:
|
||||
``item_name`` (``str``): The name of the item in the dataset.
|
||||
"""
|
||||
assert item_name in self.content, f"{item_name} is not provided in the Data"
|
||||
return (
|
||||
isinstance(self._content[item_name], dict)
|
||||
and "upon" in self._content[item_name]
|
||||
and "loader" in self._content[item_name]
|
||||
)
|
||||
|
||||
def __getitem__(self, key: str) -> Any:
|
||||
if self.needs_to_load(key):
|
||||
cur_cfg = self._content[key]
|
||||
if cur_cfg.get("cache", None) is None:
|
||||
# get raw data
|
||||
item = self.raw(key)
|
||||
# preprocess and cache
|
||||
pipes = cur_cfg.get("preprocess", None)
|
||||
if pipes is not None:
|
||||
cur_cfg["cache"] = compose_pipes(*pipes)(item)
|
||||
else:
|
||||
cur_cfg["cache"] = item
|
||||
return cur_cfg["cache"]
|
||||
else:
|
||||
return self._content[key]
|
||||
|
||||
def raw(self, key: str) -> Any:
|
||||
r"""Return the ``key`` of the dataset with un-preprocessed format."""
|
||||
if self.needs_to_load(key):
|
||||
cur_cfg = self._content[key]
|
||||
if self._raw.get(key, None) is None:
|
||||
upon = cur_cfg["upon"]
|
||||
if len(upon) == 0:
|
||||
return None
|
||||
self.fetch_files(cur_cfg["upon"])
|
||||
file_path_list = [
|
||||
self.data_root / u["filename"] for u in cur_cfg["upon"]
|
||||
]
|
||||
if len(file_path_list) == 1:
|
||||
self._raw[key] = cur_cfg["loader"](file_path_list[0])
|
||||
else:
|
||||
# here, you should implement a multi-file loader
|
||||
self._raw[key] = cur_cfg["loader"](file_path_list)
|
||||
return self._raw[key]
|
||||
else:
|
||||
return self._content[key]
|
||||
|
||||
def fetch_files(self, files: List[Dict[str, str]]):
|
||||
r"""Download and check the files if they are not exist.
|
||||
|
||||
Args:
|
||||
``files`` (``List[Dict[str, str]]``): The files to download, each element
|
||||
in the list is a dict with at lease two keys: ``filename`` and ``md5``.
|
||||
If extra key ``bk_url`` is provided, it will be used to download the
|
||||
file from the backup url.
|
||||
"""
|
||||
for file in files:
|
||||
cur_filename = file["filename"]
|
||||
cur_url = file.get("bk_url", None)
|
||||
if cur_url is None:
|
||||
cur_url = self.remote_root + cur_filename
|
||||
download_and_check(cur_url, self.data_root / cur_filename, file["md5"])
|
||||
@@ -0,0 +1,78 @@
|
||||
import os.path as osp
|
||||
|
||||
import numpy as np
|
||||
import scipy.sparse as sp
|
||||
import torch
|
||||
|
||||
from torch_geometric.data import Data
|
||||
from torch_sparse import coalesce
|
||||
|
||||
|
||||
__all__ = ["load_line_expansion_dataset"]
|
||||
|
||||
|
||||
def load_line_expansion_dataset(
|
||||
path=None, dataset="cocitation-cora", train_percent=0.5
|
||||
):
|
||||
# load edges, features, and labels.
|
||||
print("Loading {} dataset...".format(dataset))
|
||||
|
||||
file_name = f"{dataset}.content"
|
||||
p2idx_features_labels = osp.join(path, dataset, file_name)
|
||||
idx_features_labels = np.genfromtxt(p2idx_features_labels, dtype=np.dtype(str))
|
||||
# features = np.array(idx_features_labels[:, 1:-1])
|
||||
features = sp.csr_matrix(idx_features_labels[:, 1:-1], dtype=np.float32)
|
||||
# labels = encode_onehot(idx_features_labels[:, -1])
|
||||
labels = torch.LongTensor(idx_features_labels[:, -1].astype(float))
|
||||
|
||||
print("load features")
|
||||
|
||||
# build graph
|
||||
idx = np.array(idx_features_labels[:, 0], dtype=np.int32)
|
||||
idx_map = {j: i for i, j in enumerate(idx)}
|
||||
|
||||
file_name = f"{dataset}.edges"
|
||||
p2edges_unordered = osp.join(path, dataset, file_name)
|
||||
edges_unordered = np.genfromtxt(p2edges_unordered, dtype=np.int32)
|
||||
|
||||
edges = np.array(
|
||||
list(map(idx_map.get, edges_unordered.flatten())), dtype=np.int32
|
||||
).reshape(edges_unordered.shape)
|
||||
|
||||
print("load edges")
|
||||
|
||||
# From adjacency matrix to edge_list
|
||||
edge_index = edges.T
|
||||
# ipdb.set_trace()
|
||||
assert edge_index[0].max() == edge_index[1].min() - 1
|
||||
|
||||
# check if values in edge_index is consecutive. i.e. no missing value for node_id/he_id.
|
||||
assert len(np.unique(edge_index)) == edge_index.max() + 1
|
||||
|
||||
num_nodes = edge_index[0].max() + 1
|
||||
num_he = edge_index[1].max() - num_nodes + 1
|
||||
edge_index = np.hstack((edge_index, edge_index[::-1, :]))
|
||||
|
||||
# build torch data class
|
||||
data = Data(
|
||||
x=torch.FloatTensor(np.array(features[:num_nodes].todense())),
|
||||
edge_index=torch.LongTensor(edge_index),
|
||||
y=labels[:num_nodes],
|
||||
)
|
||||
|
||||
# used user function to override the default function.
|
||||
# the following will also sort the edge_index and remove duplicates.
|
||||
total_num_node_id_he_id = len(np.unique(edge_index))
|
||||
data.edge_index, data.edge_attr = coalesce(
|
||||
data.edge_index, None, total_num_node_id_he_id, total_num_node_id_he_id
|
||||
)
|
||||
n_x = num_nodes
|
||||
# n_x = n_expanded
|
||||
num_class = len(np.unique(labels[:num_nodes].numpy()))
|
||||
data.n_x = n_x
|
||||
# add parameters to attribute
|
||||
|
||||
data.train_percent = train_percent
|
||||
data.num_hyperedges = num_he
|
||||
|
||||
return data
|
||||
@@ -0,0 +1,113 @@
|
||||
import requests
|
||||
|
||||
from easygraph.utils.exception import EasyGraphError
|
||||
|
||||
|
||||
def request_text_from_url(url):
|
||||
try:
|
||||
r = requests.get(url)
|
||||
except requests.ConnectionError:
|
||||
raise EasyGraphError("Connection Error!")
|
||||
|
||||
if r.ok:
|
||||
return r.text
|
||||
else:
|
||||
raise EasyGraphError(f"Error: HTTP response {r.status_code}")
|
||||
|
||||
|
||||
class mathoverflow_answers:
|
||||
def __init__(self, data_root=None):
|
||||
self.data_root = "https://" if data_root is not None else data_root
|
||||
self.hyperedges_path = "https://gitlab.com/easy-graph/easygraph-data-mathoverflow-answers/-/raw/main/hyperedges-mathoverflow-answers.txt?inline=false"
|
||||
self.node_labels_path = "https://gitlab.com/easy-graph/easygraph-data-mathoverflow-answers/-/raw/main/node-labels-mathoverflow-answers.txt?ref_type=heads&inline=false"
|
||||
# self.node_names_path = "https://gitlab.com/easy-graph/easygraph-data-house-committees/-/raw/main/node-names-house-committees.txt?ref_type=heads&inline=false"
|
||||
self.label_names_path = "https://gitlab.com/easy-graph/easygraph-data-mathoverflow-answers/-/raw/main/label-names-mathoverflow-answers.txt?ref_type=heads&inline=false"
|
||||
self._hyperedges = []
|
||||
self._node_labels = []
|
||||
self._label_names = []
|
||||
self._node_names = []
|
||||
self.generate_hypergraph(
|
||||
hyperedges_path=self.hyperedges_path,
|
||||
node_labels_path=self.node_labels_path,
|
||||
# node_names_path=self.node_names_path,
|
||||
label_names_path=self.label_names_path,
|
||||
)
|
||||
self._content = {
|
||||
"num_classes": len(self._label_names),
|
||||
"num_vertices": len(self._node_labels),
|
||||
"num_edges": len(self._hyperedges),
|
||||
"edge_list": self._hyperedges,
|
||||
"labels": self._node_labels,
|
||||
}
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
return self._content[key]
|
||||
|
||||
def process_label_txt(self, data_str, delimiter="\n", transform_fun=str):
|
||||
data_str = data_str.strip()
|
||||
data_lst = data_str.split(delimiter)
|
||||
final_lst = []
|
||||
for data in data_lst:
|
||||
data = data.strip()
|
||||
data = transform_fun(data)
|
||||
final_lst.append(data)
|
||||
return final_lst
|
||||
|
||||
@property
|
||||
def node_labels(self):
|
||||
return self._node_labels
|
||||
|
||||
"""
|
||||
@property
|
||||
def node_names(self):
|
||||
return self._node_names
|
||||
"""
|
||||
|
||||
@property
|
||||
def label_names(self):
|
||||
return self._label_names
|
||||
|
||||
@property
|
||||
def hyperedges(self):
|
||||
return self._hyperedges
|
||||
|
||||
def generate_hypergraph(
|
||||
self,
|
||||
hyperedges_path=None,
|
||||
node_labels_path=None,
|
||||
# node_names_path=None,
|
||||
label_names_path=None,
|
||||
):
|
||||
def fun(data):
|
||||
data = int(data) - 1
|
||||
return data
|
||||
|
||||
hyperedges_info = request_text_from_url(hyperedges_path)
|
||||
hyperedges_info = hyperedges_info.strip()
|
||||
hyperedges_lst = hyperedges_info.split("\n")
|
||||
for hyperedge in hyperedges_lst:
|
||||
hyperedge = hyperedge.strip()
|
||||
hyperedge = [int(i) - 1 for i in hyperedge.split(",")]
|
||||
self._hyperedges.append(tuple(hyperedge))
|
||||
# print(self.hyperedges)
|
||||
"""
|
||||
node_labels_info = request_text_from_url(node_labels_path)
|
||||
|
||||
process_node_labels_info = self.process_label_txt(
|
||||
node_labels_info, transform_fun=fun
|
||||
)
|
||||
self._node_labels = process_node_labels_info
|
||||
"""
|
||||
node_labels_info = request_text_from_url(node_labels_path)
|
||||
node_labels_info = node_labels_info.strip()
|
||||
node_labels_lst = node_labels_info.split("\n")
|
||||
for node_label in node_labels_lst:
|
||||
node_label = node_label.strip()
|
||||
node_label = [int(i) - 1 for i in node_label.split(",")]
|
||||
self._node_labels.append(tuple(node_label))
|
||||
# print("process_node_labels_info:", process_node_labels_info)
|
||||
# print("process_node_names_info:", process_node_names_info)
|
||||
label_names_info = request_text_from_url(label_names_path)
|
||||
process_label_names_info = self.process_label_txt(label_names_info)
|
||||
self._label_names = process_label_names_info
|
||||
# print("process_label_names_info:", process_label_names_info)
|
||||
@@ -0,0 +1,106 @@
|
||||
import requests
|
||||
|
||||
from easygraph.utils.exception import EasyGraphError
|
||||
|
||||
|
||||
def request_text_from_url(url):
|
||||
try:
|
||||
r = requests.get(url)
|
||||
except requests.ConnectionError:
|
||||
raise EasyGraphError("Connection Error!")
|
||||
|
||||
if r.ok:
|
||||
return r.text
|
||||
else:
|
||||
raise EasyGraphError(f"Error: HTTP response {r.status_code}")
|
||||
|
||||
|
||||
class senate_committees:
|
||||
def __init__(self, data_root=None):
|
||||
self.data_root = "https://" if data_root is not None else data_root
|
||||
self.hyperedges_path = "https://gitlab.com/easy-graph/easygraph-data-senate-committees/-/raw/main/hyperedges-senate-committees.txt?inline=false"
|
||||
self.node_labels_path = "https://gitlab.com/easy-graph/easygraph-data-senate-committees/-/raw/main/node-labels-senate-committees.txt?ref_type=heads&inline=false"
|
||||
self.node_names_path = "https://gitlab.com/easy-graph/easygraph-data-senate-committees/-/raw/main/node-names-senate-committees.txt?ref_type=heads&inline=false"
|
||||
self.label_names_path = "https://gitlab.com/easy-graph/easygraph-data-senate-committees/-/raw/main/label-names-senate-committees.txt?ref_type=heads&inline=false"
|
||||
self._hyperedges = []
|
||||
self._node_labels = []
|
||||
self._label_names = []
|
||||
self._node_names = []
|
||||
self.generate_hypergraph(
|
||||
hyperedges_path=self.hyperedges_path,
|
||||
node_labels_path=self.node_labels_path,
|
||||
node_names_path=self.node_names_path,
|
||||
label_names_path=self.label_names_path,
|
||||
)
|
||||
self._content = {
|
||||
"num_classes": len(self._label_names),
|
||||
"num_vertices": len(self._node_labels),
|
||||
"num_edges": len(self._hyperedges),
|
||||
"edge_list": self._hyperedges,
|
||||
"labels": self._node_labels,
|
||||
}
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
return self._content[key]
|
||||
|
||||
def process_label_txt(self, data_str, delimiter="\n", transform_fun=str):
|
||||
data_str = data_str.strip()
|
||||
data_lst = data_str.split(delimiter)
|
||||
final_lst = []
|
||||
for data in data_lst:
|
||||
data = data.strip()
|
||||
data = transform_fun(data)
|
||||
final_lst.append(data)
|
||||
return final_lst
|
||||
|
||||
@property
|
||||
def node_labels(self):
|
||||
return self._node_labels
|
||||
|
||||
@property
|
||||
def node_names(self):
|
||||
return self._node_names
|
||||
|
||||
@property
|
||||
def label_names(self):
|
||||
return self._label_names
|
||||
|
||||
@property
|
||||
def hyperedges(self):
|
||||
return self._hyperedges
|
||||
|
||||
def generate_hypergraph(
|
||||
self,
|
||||
hyperedges_path=None,
|
||||
node_labels_path=None,
|
||||
node_names_path=None,
|
||||
label_names_path=None,
|
||||
):
|
||||
def fun(data):
|
||||
data = int(data) - 1
|
||||
return data
|
||||
|
||||
hyperedges_info = request_text_from_url(hyperedges_path)
|
||||
hyperedges_info = hyperedges_info.strip()
|
||||
hyperedges_lst = hyperedges_info.split("\n")
|
||||
for hyperedge in hyperedges_lst:
|
||||
hyperedge = hyperedge.strip()
|
||||
hyperedge = [int(i) - 1 for i in hyperedge.split(",")]
|
||||
self._hyperedges.append(tuple(hyperedge))
|
||||
# print(self.hyperedges)
|
||||
|
||||
node_labels_info = request_text_from_url(node_labels_path)
|
||||
|
||||
process_node_labels_info = self.process_label_txt(
|
||||
node_labels_info, transform_fun=fun
|
||||
)
|
||||
self._node_labels = process_node_labels_info
|
||||
# print("process_node_labels_info:", process_node_labels_info)
|
||||
node_names_info = request_text_from_url(node_names_path)
|
||||
process_node_names_info = self.process_label_txt(node_names_info)
|
||||
self._node_names = process_node_names_info
|
||||
# print("process_node_names_info:", process_node_names_info)
|
||||
label_names_info = request_text_from_url(label_names_path)
|
||||
process_label_names_info = self.process_label_txt(label_names_info)
|
||||
self._label_names = process_label_names_info
|
||||
# print("process_label_names_info:", process_label_names_info)
|
||||
@@ -0,0 +1,104 @@
|
||||
import requests
|
||||
|
||||
from easygraph.utils.exception import EasyGraphError
|
||||
|
||||
|
||||
def request_text_from_url(url):
|
||||
try:
|
||||
r = requests.get(url)
|
||||
except requests.ConnectionError:
|
||||
raise EasyGraphError("Connection Error!")
|
||||
|
||||
if r.ok:
|
||||
return r.text
|
||||
else:
|
||||
raise EasyGraphError(f"Error: HTTP response {r.status_code}")
|
||||
|
||||
|
||||
class trivago_clicks:
|
||||
def __init__(self, data_root=None):
|
||||
self.data_root = "https://" if data_root is not None else data_root
|
||||
self.hyperedges_path = "https://gitlab.com/easy-graph/easygraph-data-trivago-clicks/-/raw/main/hyperedges-trivago-clicks.txt?inline=false"
|
||||
self.node_labels_path = "https://gitlab.com/easy-graph/easygraph-data-trivago-clicks/-/raw/main/node-labels-trivago-clicks.txt?ref_type=heads&inline=false"
|
||||
# self.node_names_path = "https://gitlab.com/easy-graph/easygraph-data-trivago-clicks/-/raw/main/node-names-house-committees.txt?ref_type=heads&inline=false"
|
||||
self.label_names_path = "https://gitlab.com/easy-graph/easygraph-data-trivago-clicks/-/raw/main/label-names-trivago-clicks.txt?ref_type=heads&inline=false"
|
||||
self._hyperedges = []
|
||||
self._node_labels = []
|
||||
self._label_names = []
|
||||
self._node_names = []
|
||||
self.generate_hypergraph(
|
||||
hyperedges_path=self.hyperedges_path,
|
||||
node_labels_path=self.node_labels_path,
|
||||
# node_names_path=self.node_names_path,
|
||||
label_names_path=self.label_names_path,
|
||||
)
|
||||
self._content = {
|
||||
"num_classes": len(self._label_names),
|
||||
"num_vertices": len(self._node_labels),
|
||||
"num_edges": len(self._hyperedges),
|
||||
"edge_list": self._hyperedges,
|
||||
"labels": self._node_labels,
|
||||
}
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
return self._content[key]
|
||||
|
||||
def process_label_txt(self, data_str, delimiter="\n", transform_fun=str):
|
||||
data_str = data_str.strip()
|
||||
data_lst = data_str.split(delimiter)
|
||||
final_lst = []
|
||||
for data in data_lst:
|
||||
data = data.strip()
|
||||
data = transform_fun(data)
|
||||
final_lst.append(data)
|
||||
return final_lst
|
||||
|
||||
@property
|
||||
def node_labels(self):
|
||||
return self._node_labels
|
||||
|
||||
"""
|
||||
@property
|
||||
def node_names(self):
|
||||
return self._node_names
|
||||
"""
|
||||
|
||||
@property
|
||||
def label_names(self):
|
||||
return self._label_names
|
||||
|
||||
@property
|
||||
def hyperedges(self):
|
||||
return self._hyperedges
|
||||
|
||||
def generate_hypergraph(
|
||||
self,
|
||||
hyperedges_path=None,
|
||||
node_labels_path=None,
|
||||
# node_names_path=None,
|
||||
label_names_path=None,
|
||||
):
|
||||
def fun(data):
|
||||
data = int(data) - 1
|
||||
return data
|
||||
|
||||
hyperedges_info = request_text_from_url(hyperedges_path)
|
||||
hyperedges_info = hyperedges_info.strip()
|
||||
hyperedges_lst = hyperedges_info.split("\n")
|
||||
for hyperedge in hyperedges_lst:
|
||||
hyperedge = hyperedge.strip()
|
||||
hyperedge = [int(i) - 1 for i in hyperedge.split(",")]
|
||||
self._hyperedges.append(tuple(hyperedge))
|
||||
# print(self.hyperedges)
|
||||
|
||||
node_labels_info = request_text_from_url(node_labels_path)
|
||||
|
||||
process_node_labels_info = self.process_label_txt(
|
||||
node_labels_info, transform_fun=fun
|
||||
)
|
||||
self._node_labels = process_node_labels_info
|
||||
# print("process_node_labels_info:", process_node_labels_info)
|
||||
# print("process_node_names_info:", process_node_names_info)
|
||||
label_names_info = request_text_from_url(label_names_path)
|
||||
process_label_names_info = self.process_label_txt(label_names_info)
|
||||
self._label_names = process_label_names_info
|
||||
@@ -0,0 +1,208 @@
|
||||
import requests
|
||||
|
||||
from easygraph.utils.exception import EasyGraphError
|
||||
|
||||
|
||||
def request_text_from_url(url):
|
||||
"""
|
||||
Requests text content from the given URL.
|
||||
|
||||
Args:
|
||||
url (str): The URL from which to request text data.
|
||||
|
||||
Returns:
|
||||
str: The text content of the response if the request is successful.
|
||||
|
||||
Raises:
|
||||
EasyGraphError: If a connection error occurs during the request or if the HTTP response status code is not OK.
|
||||
"""
|
||||
try:
|
||||
r = requests.get(url)
|
||||
except requests.ConnectionError:
|
||||
raise EasyGraphError("Connection Error!")
|
||||
|
||||
if r.ok:
|
||||
return r.text
|
||||
else:
|
||||
raise EasyGraphError(f"Error: HTTP response {r.status_code}")
|
||||
|
||||
|
||||
class walmart_trips:
|
||||
"""
|
||||
A class for loading and processing the Walmart trips hypergraph dataset.
|
||||
|
||||
This class fetches hyperedge, node label, and label name data from predefined URLs,
|
||||
processes the data, and generates a hypergraph representation. It also provides access
|
||||
to various dataset attributes through properties and indexing.
|
||||
|
||||
Attributes:
|
||||
data_root (str): The root URL for the data. If provided during initialization, it is set to "https://";
|
||||
otherwise, it is None.
|
||||
hyperedges_path (str): The URL of the file containing hyperedge information.
|
||||
node_labels_path (str): The URL of the file containing node label information.
|
||||
label_names_path (str): The URL of the file containing label name information.
|
||||
_hyperedges (list): A list of tuples representing hyperedges.
|
||||
_node_labels (list): A list of node labels.
|
||||
_label_names (list): A list of label names.
|
||||
_node_names (list): An empty list reserved for node names (currently unused).
|
||||
_content (dict): A dictionary containing dataset statistics and data, such as the number of classes,
|
||||
vertices, edges, the edge list, and node labels.
|
||||
"""
|
||||
|
||||
def __init__(self, data_root=None, local_path=None):
|
||||
"""
|
||||
Initializes an instance of the walmart_trips class.
|
||||
|
||||
Args:
|
||||
data_root (str, optional): The root URL for the data. If provided, it is set to "https://";
|
||||
otherwise, it is None. Defaults to None.
|
||||
local_path (str, optional): Currently unused. Defaults to None.
|
||||
"""
|
||||
self.data_root = "https://" if data_root is not None else data_root
|
||||
self.hyperedges_path = "https://gitlab.com/easy-graph/easygraph-data-walmart-trips/-/raw/main/hyperedges-walmart-trips.txt?inline=false"
|
||||
self.node_labels_path = "https://gitlab.com/easy-graph/easygraph-data-walmart-trips/-/raw/main/node-labels-walmart-trips.txt?ref_type=heads&inline=false"
|
||||
# self.node_names_path = "https://gitlab.com/easy-graph/easygraph-data-walmart-trips/-/raw/main/node-names-house-committees.txt?ref_type=heads&inline=false"
|
||||
self.label_names_path = "https://gitlab.com/easy-graph/easygraph-data-walmart-trips/-/raw/main/label-names-walmart-trips.txt?ref_type=heads&inline=false"
|
||||
self._hyperedges = []
|
||||
self._node_labels = []
|
||||
self._label_names = []
|
||||
self._node_names = []
|
||||
|
||||
self.generate_hypergraph(
|
||||
hyperedges_path=self.hyperedges_path,
|
||||
node_labels_path=self.node_labels_path,
|
||||
# node_names_path=self.node_names_path,
|
||||
label_names_path=self.label_names_path,
|
||||
)
|
||||
|
||||
self._content = {
|
||||
"num_classes": len(self._label_names),
|
||||
"num_vertices": len(self._node_labels),
|
||||
"num_edges": len(self._hyperedges),
|
||||
"edge_list": self._hyperedges,
|
||||
"labels": self._node_labels,
|
||||
}
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
"""
|
||||
Retrieves a value from the _content dictionary using the specified key.
|
||||
|
||||
Args:
|
||||
key (str): The key used to access the _content dictionary.
|
||||
|
||||
Returns:
|
||||
Any: The value corresponding to the key in the _content dictionary.
|
||||
"""
|
||||
return self._content[key]
|
||||
|
||||
def process_label_txt(self, data_str, delimiter="\n", transform_fun=str):
|
||||
"""
|
||||
Processes a string containing label data into a list of transformed values.
|
||||
|
||||
Args:
|
||||
data_str (str): The input string containing label data.
|
||||
delimiter (str, optional): The delimiter used to split the input string. Defaults to "\n".
|
||||
transform_fun (callable, optional): A function used to transform each label value.
|
||||
Defaults to the str function.
|
||||
|
||||
Returns:
|
||||
list: A list of transformed label values.
|
||||
"""
|
||||
data_str = data_str.strip()
|
||||
data_lst = data_str.split(delimiter)
|
||||
final_lst = []
|
||||
for data in data_lst:
|
||||
data = data.strip()
|
||||
data = transform_fun(data)
|
||||
final_lst.append(data)
|
||||
return final_lst
|
||||
|
||||
@property
|
||||
def node_labels(self):
|
||||
"""
|
||||
Gets the list of node labels.
|
||||
|
||||
Returns:
|
||||
list: A list of node labels.
|
||||
"""
|
||||
return self._node_labels
|
||||
|
||||
"""
|
||||
@property
|
||||
def node_names(self):
|
||||
return self._node_names
|
||||
"""
|
||||
|
||||
@property
|
||||
def label_names(self):
|
||||
"""
|
||||
Gets the list of label names.
|
||||
|
||||
Returns:
|
||||
list: A list of label names.
|
||||
"""
|
||||
return self._label_names
|
||||
|
||||
@property
|
||||
def hyperedges(self):
|
||||
"""
|
||||
Gets the list of hyperedges.
|
||||
|
||||
Returns:
|
||||
list: A list of tuples representing hyperedges.
|
||||
"""
|
||||
return self._hyperedges
|
||||
|
||||
def generate_hypergraph(
|
||||
self,
|
||||
hyperedges_path=None,
|
||||
node_labels_path=None,
|
||||
# node_names_path=None,
|
||||
label_names_path=None,
|
||||
):
|
||||
"""
|
||||
Generates a hypergraph by fetching and processing data from the specified URLs.
|
||||
|
||||
Args:
|
||||
hyperedges_path (str, optional): The URL of the file containing hyperedge information.
|
||||
Defaults to None.
|
||||
node_labels_path (str, optional): The URL of the file containing node label information.
|
||||
Defaults to None.
|
||||
label_names_path (str, optional): The URL of the file containing label name information.
|
||||
Defaults to None.
|
||||
"""
|
||||
|
||||
def fun(data):
|
||||
"""
|
||||
Converts a string to an integer and subtracts 1.
|
||||
|
||||
Args:
|
||||
data (str): The input string to be converted.
|
||||
|
||||
Returns:
|
||||
int: The converted integer value minus 1.
|
||||
"""
|
||||
data = int(data) - 1
|
||||
return data
|
||||
|
||||
hyperedges_info = request_text_from_url(hyperedges_path)
|
||||
hyperedges_info = hyperedges_info.strip()
|
||||
hyperedges_lst = hyperedges_info.split("\n")
|
||||
for hyperedge in hyperedges_lst:
|
||||
hyperedge = hyperedge.strip()
|
||||
hyperedge = [int(i) - 1 for i in hyperedge.split(",")]
|
||||
self._hyperedges.append(tuple(hyperedge))
|
||||
# print(self.hyperedges)
|
||||
|
||||
node_labels_info = request_text_from_url(node_labels_path)
|
||||
|
||||
process_node_labels_info = self.process_label_txt(
|
||||
node_labels_info, transform_fun=fun
|
||||
)
|
||||
self._node_labels = process_node_labels_info
|
||||
# print("process_node_labels_info:", process_node_labels_info)
|
||||
# print("process_node_names_info:", process_node_names_info)
|
||||
label_names_info = request_text_from_url(label_names_path)
|
||||
process_label_names_info = self.process_label_txt(label_names_info)
|
||||
self._label_names = process_label_names_info
|
||||
# print("process_label_names_info:", process_label_names_info)
|
||||
Reference in New Issue
Block a user