Skip to content

Commit 50a5297

Browse files
Implementation of the DnD lfiting (Graph to Complex)
1 parent 153b620 commit 50a5297

File tree

8 files changed

+956
-546
lines changed

8 files changed

+956
-546
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
transform_type: 'lifting'
2-
transform_name: "SimplicialEccentricityLifting"
3-
complex_dim: 3
2+
transform_name: "SimplicialDnDLifting"
3+
complex_dim: 6
44
preserve_edge_attr: False
55
signed: True
66
feature_lifting: ProjectionSum

modules/transforms/data_transform.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@
1515
from modules.transforms.liftings.graph2simplicial.clique_lifting import (
1616
SimplicialCliqueLifting,
1717
)
18-
from modules.transforms.liftings.graph2simplicial.eccentricity_lifting import (
19-
SimplicialEccentricityLifting,
18+
from modules.transforms.liftings.graph2simplicial.dnd_lifting import (
19+
SimplicialDnDLifting,
2020
)
2121

2222
TRANSFORMS = {
2323
# Graph -> Hypergraph
2424
"HypergraphKNNLifting": HypergraphKNNLifting,
2525
# Graph -> Simplicial Complex
2626
"SimplicialCliqueLifting": SimplicialCliqueLifting,
27-
"SimplicialEccentricityLifting": SimplicialEccentricityLifting,
27+
"SimplicialDnDLifting": SimplicialDnDLifting,
2828
# Graph -> Cell Complex
2929
"CellCycleLifting": CellCycleLifting,
3030
# Feature Liftings
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import random
2+
from itertools import combinations
3+
4+
import networkx as nx
5+
from toponetx.classes import SimplicialComplex
6+
from torch_geometric.data import Data
7+
8+
from modules.transforms.liftings.graph2simplicial.base import Graph2SimplicialLifting
9+
10+
11+
class SimplicialDnDLifting(Graph2SimplicialLifting):
12+
r"""Lifts graphs to simplicial complex domain using a Dungeons & Dragons inspired system.
13+
14+
Parameters
15+
----------
16+
**kwargs : optional
17+
Additional arguments for the class.
18+
"""
19+
20+
def __init__(self, **kwargs):
21+
super().__init__(**kwargs)
22+
23+
def lift_topology(self, data: Data) -> dict:
24+
r"""Lifts the topology of a graph to a simplicial complex using Dungeons & Dragons (D&D) inspired mechanics.
25+
26+
Parameters
27+
----------
28+
data : Data
29+
The input data to be lifted.
30+
31+
Returns
32+
-------
33+
dict
34+
The lifted topology.
35+
"""
36+
graph = self._generate_graph_from_data(data)
37+
simplicial_complex = SimplicialComplex()
38+
39+
characters = self._assign_attributes(graph)
40+
simplices = [set() for _ in range(2, self.complex_dim + 1)]
41+
42+
for node in graph.nodes:
43+
simplicial_complex.add_node(node, features=data.x[node])
44+
45+
for node in graph.nodes:
46+
character = characters[node]
47+
for k in range(1, self.complex_dim):
48+
dice_roll = self._roll_dice(character, k)
49+
neighborhood = list(
50+
nx.single_source_shortest_path_length(
51+
graph, node, cutoff=dice_roll
52+
).keys()
53+
)
54+
for combination in combinations(neighborhood, k + 1):
55+
simplices[k - 1].add(tuple(sorted(combination)))
56+
57+
for set_k_simplices in simplices:
58+
simplicial_complex.add_simplices_from(list(set_k_simplices))
59+
60+
return self._get_lifted_topology(simplicial_complex, graph)
61+
62+
def _assign_attributes(self, graph):
63+
"""Assign D&D-inspired attributes based on node properties."""
64+
degrees = nx.degree_centrality(graph)
65+
clustering = nx.clustering(graph)
66+
closeness = nx.closeness_centrality(graph)
67+
eigenvector = nx.eigenvector_centrality(graph)
68+
betweenness = nx.betweenness_centrality(graph)
69+
pagerank = nx.pagerank(graph)
70+
71+
attributes = {}
72+
for node in graph.nodes:
73+
attributes[node] = {
74+
"Degree": degrees[node],
75+
"Clustering": clustering[node],
76+
"Closeness": closeness[node],
77+
"Eigenvector": eigenvector[node],
78+
"Betweenness": betweenness[node],
79+
"Pagerank": pagerank[node],
80+
}
81+
return attributes
82+
83+
def _roll_dice(self, attributes, k):
84+
"""Simulate a D20 dice roll influenced by node attributes where a different attribute is used based on the simplex level."""
85+
86+
attribute = None
87+
if k == 1:
88+
attribute = attributes["Degree"]
89+
elif k == 2:
90+
attribute = attributes["Clustering"]
91+
elif k == 3:
92+
attribute = attributes["Closeness"]
93+
elif k == 4:
94+
attribute = attributes["Eigenvector"]
95+
elif k == 5:
96+
attribute = attributes["Betweenness"]
97+
else:
98+
attribute = attributes["Pagerank"]
99+
100+
base_roll = random.randint(1, 20)
101+
modifier = int(attribute * 20)
102+
return base_roll + modifier

modules/transforms/liftings/graph2simplicial/eccentricity_lifting.py

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)