EvoRM / code /Area1 /struc_sim.py
eduzrh's picture
Upload code/Area1/struc_sim.py with huggingface_hub
4818e0e verified
Raw
History Blame Contribute Delete
2.78 kB
import math
from collections import defaultdict
def load_triples(file_path):
"""Construct neighboring dictionaries containing isolated nodes (automatically includes all entities)"""
adj = defaultdict(set)
entities = set() # Record all occurrences of the entity
with open(file_path, 'r') as f:
for line in f:
parts = line.strip().split('\t')
h = parts[0]
t = parts[2]
entities.update([h, t])
adj[h].add(t)
adj[t].add(h)
# Ensure that isolated entities exist in the adjacency dictionary (empty neighbors)
for e in entities:
_ = adj[e] # Trigger defaultdict to automatically create empty collection
return adj
def load_ref_ent_ids(file_path):
"""Load alignments, no longer filtering any entities"""
S_pairs = []
with open(file_path, 'r') as f:
for line in f:
src, tgt = line.strip().split('\t')
S_pairs.append((src, tgt))
return S_pairs
def structure_similarity(kg1_adj, kg2_adj, S_pairs):
"""Improved structural similarity computation dealing with three neighbor cases"""
if not S_pairs:
return 0.0
total_sim = 0.0
m = len(S_pairs)
S_src = [pair[0] for pair in S_pairs]
S_tgt = [pair[1] for pair in S_pairs]
for (i, j) in S_pairs:
# Get the set of neighbors (all entities exist in the adjacency dictionary at this point)
neighbors_i = kg1_adj[i]
neighbors_j = kg2_adj[j]
# Scenario 1: Neither party has a neighbor
if not neighbors_i and not neighbors_j:
sim = 1.0 # The structure is identical
# Scenario 2: One of the parties has no neighbors
elif not neighbors_i or not neighbors_j:
sim = 0.0 # Complete mismatch in structure
# Scenario 3: Neighbors on both sides
else:
# Constructing projection vectors based on alignment spaces
v1 = [1 if x in neighbors_i else 0 for x in S_src]
v2 = [1 if y in neighbors_j else 0 for y in S_tgt]
# Calculate cosine similarity
dot_product = sum(a * b for a, b in zip(v1, v2))
norm_v1 = math.sqrt(sum(a ** 2 for a in v1))
norm_v2 = math.sqrt(sum(b ** 2 for b in v2))
sim = dot_product / (norm_v1 * norm_v2) if norm_v1 * norm_v2 != 0 else 0.0
total_sim += sim
return total_sim / m
if __name__ == '__main__':
# Note: load_triples will now contain all entities
kg1_adj = load_triples('triples_1')
kg2_adj = load_triples('triples_2')
aligned_pairs = load_ref_ent_ids('ref_ent_ids')
similarity = structure_similarity(kg1_adj, kg2_adj, aligned_pairs)
print(f"Structure Similarity: {similarity:.4f}")