Standard recommendation systems often focus only on how well a result matches a search, ignoring the logical path or context needed to get there.
It ranks items by combining how closely they match a user's intent with the logical steps or pathing required to reach that result.
It provides a more balanced ranking system that considers both the meaning of a result and the context of the journey to find it.
It was run in the sandbox and it failed. run output shows an error/traceback — the artifact does NOT run clean.
$ python3 trace_augmented_recommendation.py Recommendations based on Trace-Augmented Score: item2: 0.71 item3: 0.71 item4: 0.71 item1: 0.70 Score breakdown: item2: Path=0.43, Semantic=0.99, Combined=0.71 item3: Path=0.43, Semantic=0.99, Combined=0.71 item4: Path=0.43, Semantic=0.98, Combined=0.71 item1: Path=0.43, Semantic=0.96, Combined=0.70
No screenshot — there is nothing working to show. This is recorded as an unfinished sketch so the attempt stays visible instead of being quietly dropped.
All of it — 198 lines, one file, standard library only.
# Trace-Augmented Recommendation Score v2 -- with Path-Diversity filter
import math
from collections import defaultdict
class TraceAugmentedRecommender:
def __init__(self, graph, features, alpha=0.5):
self.graph = graph
self.features = features
self.alpha = alpha
self.nodes = list(self.graph.keys())
self.path_scores = {}
self.semantic_similarities = {}
self.diversity_penalties = {}
self.diverse_scores = {}
self.combine_scores()
def calculate_path_scores(self):
for node in self.graph:
total_distance = 0
reachable_count = 0
for other in self.graph:
if node != other:
distance = self.bfs_distance(node, other)
if distance != float('inf'):
total_distance += distance
reachable_count += 1
if reachable_count > 0:
self.path_scores[node] = 1 / (1 + total_distance / reachable_count)
def calculate_semantic_similarity(self):
nodes = self.nodes
for i, node_i in enumerate(nodes):
vec_i = self.features[node_i]
for j, node_j in enumerate(nodes):
if i != j:
vec_j = self.features[node_j]
similarity = self.cosine_similarity(vec_i, vec_j)
if node_i not in self.semantic_similarities:
self.semantic_similarities[node_i] = {}
self.semantic_similarities[node_i][node_j] = similarity
def combine_scores(self):
self.calculate_path_scores()
self.calculate_semantic_similarity()
self.combined_scores = {}
for node in self.nodes:
path_contribution = self.path_scores.get(node, 0)
sims = self.semantic_similarities.get(node, {})
semantic_score = sum(sims.values()) / len(sims) if sims else 0
self.combined_scores[node] = self.alpha * path_contribution + (1 - self.alpha) * semantic_score
def bfs_distance(self, start, end):
visited = set()
queue = [(start, 0)]
while queue:
node, dist = queue.pop(0)
if node == end:
return dist
if node not in visited:
visited.add(node)
for neighbor in self.graph.get(node, []):
queue.append((neighbor, dist + 1))
return float('inf')
def bfs_path(self, start, end):
visited = set()
queue = [(start, [start])]
while queue:
node, path = queue.pop(0)
if node == end:
return path
if node not in visited:
visited.add(node)
for neighbor in self.graph.get(node, []):
if neighbor not in visited:
queue.append((neighbor, path + [neighbor]))
return []
def cosine_similarity(self, vec1, vec2):
dot_product = sum(a*b for a, b in zip(vec1, vec2))
magnitude1 = math.sqrt(sum(x**2 for x in vec1))
magnitude2 = math.sqrt(sum(x**2 for x in vec2))
if magnitude1 == 0 or magnitude2 == 0:
return 0
return dot_product / (magnitude1 * magnitude2)
def get_recommendations(self, top_n=5):
return sorted(self.combined_scores.items(), key=lambda x: x[1], reverse=True)[:top_n]
# ── V2: Path-Diversity filter ──
def compute_diversity_penalties(self, source_node):
edge_frequency = defaultdict(int)
all_paths = []
for u in self.nodes:
for v in self.nodes:
if u != v:
path = self.bfs_path(u, v)
if path:
all_paths.append((u, v, path))
for i in range(len(path) - 1):
edge = tuple(sorted([path[i], path[i+1]]))
edge_frequency[edge] += 1
total_paths = len(all_paths)
if total_paths == 0:
self.diversity_penalties = {n: 0.0 for n in self.nodes}
return
for target in self.nodes:
if target == source_node:
self.diversity_penalties[target] = 0.0
continue
path = self.bfs_path(source_node, target)
if not path or len(path) < 2:
self.diversity_penalties[target] = 0.0
continue
shared_sum = 0.0
for i in range(len(path) - 1):
edge = tuple(sorted([path[i], path[i+1]]))
freq = edge_frequency.get(edge, 0)
shared_sum += freq / total_paths
self.diversity_penalties[target] = shared_sum / (len(path) - 1)
def apply_diversity_filter(self, source_node, lambda_d=1.0):
self._compute_diversity_penalties(source_node)
self.diverse_scores = {}
for node, base_score in self.combined_scores.items():
if node == source_node:
continue
penalty = self.diversity_penalties.get(node, 0.0)
self.diverse_scores[node] = base_score / (1 + lambda_d * penalty)
def get_diverse_recommendations(self, source_node, top_n=5, lambda_d=1.0):
self.apply_diversity_filter(source_node, lambda_d)
return sorted(self.diverse_scores.items(), key=lambda x: x[1], reverse=True)[:top_n]
# Example usage
if __name__ == "__main__":
graph = {
'item1': ['item2', 'item3'],
'item2': ['item1', 'item4', 'item5'],
'item3': ['item1', 'item4', 'item5'],
'item4': ['item2', 'item3', 'item6'],
'item5': ['item2', 'item3', 'item6'],
'item6': ['item4', 'item5']
}
features = {
'item1': [1, 2, 3],
'item2': [4, 5, 6],
'item3': [7, 8, 9],
'item4': [2, 3, 1],
'item5': [5, 6, 4],
'item6': [8, 9, 7]
}
recommender = TraceAugmentedRecommender(graph, features, alpha=0.5)
recommendations = recommender.get_recommendations()
print("=== V1: Trace-Augmented Recommendation Score ===")
for item, score in recommendations:
print(f" {item}: {score:.3f}")
print("\n=== V2: Diversity-Aware Recommendations (source=item1, lambda_d=1.0) ===")
diverse = recommender.get_diverse_recommendations(source_node='item1', top_n=5, lambda_d=1.0)
for item, score in diverse:
original = recommender.combined_scores[item]
penalty = recommender.diversity_penalties.get(item, 0.0)
print(f" {item}: original={original:.3f} penalty={penalty:.3f} final={score:.3f}")
print("\n=== Detailed comparison (V1 vs V2, source=item1) ===")
for item in sorted(recommender.combined_scores.keys()):
if item == 'item1':
continue
v1 = recommender.combined_scores[item]
v2 = recommender.diverse_scores.get(item, 0.0)
penalty = recommender.diversity_penalties.get(item, 0.0)
delta = v2 - v1
arrow = "↓" if delta < 0 else "↑"
path = recommender.bfs_path('item1', item)
print(f" {item}: V1={v1:.3f} -> V2={v2:.3f} {arrow} (penalty={penalty:.3f}) path={'->'.join(path)}")
print("\n=== Edge frequency analysis ===")
edge_freq = defaultdict(int)
for u in recommender.nodes:
for v in recommender.nodes:
if u != v:
path = recommender.bfs_path(u, v)
if path:
for i in range(len(path) - 1):
edge = tuple(sorted([path[i], path[i+1]]))
edge_freq[edge] += 1
total = sum(1 for u in recommender.nodes for v in recommender.nodes if u != v and recommender.bfs_path(u, v))
for (a, b), count in sorted(edge_freq.items(), key=lambda x: -x[1]):
freq_pct = count / total * 100 if total else 0
print(f" {a}--{b}: {count} occurrences ({freq_pct:.1f}% of all-pair paths)")