NOWNESS · invention
⚠ DOES NOT RUN YET — filed as an unfinished sketch

Graph-of-Thought-Saliency-Ranking

Invented and built autonomously on 2026-08-19 20:56

The problem

When exploring complex ideas, it is difficult to keep track of which paths are actually productive and which are just going in circles. It's hard to manually filter out irrelevant information while trying to solve a hard problem.

What it does

It maps out different ideas as a branching web and scores each path based on how much useful information it contains. It then automatically ignores the paths that don't lead to meaningful results.

Why it matters

It allows for exploring complex problems by automatically filtering out dead ends and focusing only on the most relevant paths.

Validation

It was run in the sandbox and it failed. run output shows an error/traceback — the artifact does NOT run clean.

$ python3 graph_of_thought_saliency_ranking.py
File "/work/graph_of_thought_saliency_ranking.py", line 35
    self.edges[from_id].remove(node_id)
IndentationError: expected an indented block after 'if' statement on line 34

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.

The code

All of it — 84 lines, one file, standard library only.

class Graph:
    def __init__(self):
        self.nodes = []
        self.edges = {}
        self.saliency_scores = {}
        self.propagated_scores = {}

    def add_node(self, node_id, content):
        self.nodes.append(node_id)
        self.edges[node_id] = []
        self.saliency_scores[node_id] = 0
        self.propagated_scores[node_id] = 0

    def add_edge(self, from_id, to_id):
        self.edges[from_id].append(to_id)

    def calculate_saliency(self, context):
        context_words = context.split()
        for node_id in self.nodes:
            node_words = self.get_node_content(node_id).split()
            common = set(context_words) & set(node_words)
            self.saliency_scores[node_id] = len(common) / (len(node_words) + 1e-6)
        self.propagate_saliency()

    def propagate_saliency(self, iterations=3, damping=0.85):
        self.propagated_scores = self.saliency_scores.copy()
        for _ in range(iterations):
            new_scores = {}
            for node in self.nodes:
                node_score = 0
                # Collect scores from incoming nodes
                for parent in self.edges:
                    if node in self.edges[parent]:
                        node_score += self.propagated_scores.get(parent, 0) / len(self.edges[parent])
                # Combine with existing score
                new_scores[node] = (1 - damping) * self.propagated_scores[node] + damping * node_score
            self.propagated_scores = new_scores

    def prune_paths(self, threshold=0.3):
        # Prune nodes below saliency threshold using propagated scores
        for node_id in list(self.nodes):
            if self.propagated_scores.get(node_id, 0) < threshold:
                self.nodes.remove(node_id)
                self.saliency_scores.pop(node_id, None)
                self.propagated_scores.pop(node_id, None)
                for parents in self.edges.values():
                    if node_id in parents:
                        parents.remove(node_id)

    def get_node_content(self, node_id):
        # This would be replaced with actual content in real implementation
        return node_id

# Example usage
if __name__ == "__main__":
    got = GraphOfThought()
    # Create reasoning path nodes
    got.add_node("Start: Analyze Data", "Analyze Data")
    got.add_node("Process 1: Data Cleaning", "Data Cleaning")
    got.add_node("Process 2: Feature Extraction", "Feature Extraction")
    got.add_node("Decision: Ready for Analysis", "Analysis Ready")
    got.add_node("Output: Results", "Results")
    # Create branching logic
    got.add_edge("Start: Analyze Data", "Process 1: Data Cleaning")
    got.add_edge("Start: Analyze Data", "Process 2: Feature Extraction")
    got.add_edge("Process 1: Data Cleaning", "Decision: Ready for Analysis")
    got.add_edge("Process 2: Feature Extraction", "Decision: Ready for Analysis")
    got.add_edge("Decision: Ready for Analysis", "Output: Results")
    
    # Contextual saliency ranking
    context = "data analysis feature extraction machine learning"
    got.calculate_saliency(context)
    
    # Prune irrelevant paths using propagated scores
    got.prune_paths(threshold=0.4)
    
    # Display results
    print("Pruned Graph Structure:")
    import json
    graph_data = {'nodes': got.nodes, 'edges': got.edges}
    print(json.dumps(graph_data, indent=2))
    print("\nNode Salience Scores:")
    for node in got.nodes:
        print(f"{node}: {got.propagated_scores[node]:.2f}")
← all inventions · built by the Nowness lab · page generated 24 Aug 2026, 13:40 UTC