It is difficult to track if a sequence of events or movements remains logically consistent over time. Tracking these changes becomes messy when multiple factors shift at once.
It analyzes a series of state changes and assigns a score based on how well they flow together. It looks at how one step leads to the next to ensure the progression makes sense.
It provides a clear way to measure the logical consistency of complex sequences.
It was run inside an isolated container with no network access. This is the exact command and the real output it produced — captured process output, not written by a model.
$ python3 sst_score.py
Traceback (most recent call last):
File "/work/sst_score.py", line 59, in <module>
ssm.add_transition(state1, state2, 0.8)
File "/work/sst_score.py", line 14, in add_transition
if current not in self.transitions:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'State'A screenshot of that run.
A clean run proves this does what is shown above, in a CPU-only sandbox. It is a small research demo — not a production tool, and nothing here was published anywhere.
All of it — 113 lines, one file, standard library only.
import math
from dataclasses import dataclass
class State:
def __init__(self, name: str):
self.name = name
self._hash = hash(name)
def __hash__(self):
return self._hash
def __eq__(self, other):
return isinstance(other, State) and self.name == other.name
def __repr__(self):
return f"State(name='{self.name}')"
class SpatioTemporalStateSpace:
def __init__(self):
self.transitions = {} # State -> {State: probability}
self.feasibility_graph = {} # State -> {State: bool}
def add_transition(self, current: State, next_state: State, probability: float):
if current not in self.transitions:
self.transitions[current] = {}
self.transitions[current][next_state] = probability
def add_feasibility_edge(self, current: State, next_state: State):
if current not in self.feasibility_graph:
self.feasibility_graph[current] = set()
self.feasibility_graph[current].add(next_state)
def is_feasible(self, current: State, next_state: State) -> bool:
return current in self.feasibility_graph and next_state in self.feasibility_graph[current]
def transition_probability(self, current: State, next_state: State) -> float:
if current in self.transitions and next_state in self.transitions[current]:
return self.transitions[current][next_state]
return 0.0
def compute_transition_score(self, current: State, next_state: State) -> float:
prob = self.transition_probability(current, next_state)
feasible = self.is_feasible(current, next_state)
if not feasible:
return 0.0
return prob
def score_sequence(self, sequence: list[State]) -> float:
score = 1.0
for i in range(len(sequence) - 1):
current = sequence[i]
next_state = sequence[i+1]
transition_score = self.compute_transition_score(current, next_state)
score *= transition_score
if score == 0:
break
return score
def entropy_weighted_path_analysis(self, sequence: list[State]) -> float:
total_surprise = 0.0
for i in range(len(sequence) - 1):
current = sequence[i]
next_state = sequence[i+1]
if not self.is_feasible(current, next_state):
total_surprise = float('inf') # Infinite surprise for impossible transitions
break
prob = self.transition_probability(current, next_state)
if prob <= 0.0:
total_surprise = float('inf') # Zero probability transitions have infinite surprise
break
surprise = -math.log2(prob)
total_surprise += surprise
return total_surprise
# Example usage:
if __name__ == "__main__":
ssm = SpatioTemporalStateSpace()
# Define states
state1 = State("A")
state2 = State("B")
state3 = State("C")
# Add transitions with probabilities
ssm.add_transition(state1, state2, 0.8)
ssm.add_transition(state2, state3, 0.7)
state3_additions = [State("A"), State("D")]
for next_state in state3_additions:
ssm.add_transition(state3, next_state, 0.5)
# Add feasibility edges
ssm.add_feasibility_edge(state1, state2)
ssm.add_feasibility_edge(state2, state3)
ssm.add_feasibility_edge(state3, state1)
# Example sequences
sequence1 = [state1, state2, state3, state1]
sequence2 = [state1, state2, state3, State("D")]
# Calculate scores
score1 = ssm.score_sequence(sequence1)
entropy1 = ssm.entropy_weighted_path_analysis(sequence1)
score2 = ssm.score_sequence(sequence2)
entropy2 = ssm.entropy_weighted_path_analysis(sequence2)
# Output results
print(f"Sequence 1 Transition Score: {score1:.4f}")
print(f"Sequence 1 Entropy-Weighted Analysis: {entropy1:.4f} bits")
print(f"Sequence 2 Transition Score: {score2:.4f}")
print(f"Sequence 2 Entropy-Weighted Analysis: {entropy2:.4f} bits")