Computations
A Computation wraps a Poset with clock management, event recording, and rich query methods. While a Poset is the raw causal graph, a Computation is the primary interface you use to model and inspect a running system.
Recording Events
Use record() to add events to a computation. Like Poset.add(), you can
specify causal predecessors with caused_by.
1from pyrapide import Computation, Event
2
3comp = Computation()
4
5e1 = Event(name="start", source="main")
6e2 = Event(name="process", source="worker")
7e3 = Event(name="complete", source="worker")
8
9comp.record(e1)
10comp.record(e2, caused_by=[e1])
11comp.record(e3, caused_by=[e2])
12
13print(len(comp)) # 3
14print(comp.causal_depth()) # 2
15print(comp.root_events()) # {e1}
16print(comp.leaf_events()) # {e3}
17print(comp.causal_chain(e1, e3)) # [e1, e2, e3]
Query Methods
Computations provide a comprehensive set of methods for inspecting the causal structure:
len(comp): the total number of recorded events.causal_depth(): the length of the longest causal chain (number of edges).root_events(): events with no predecessors (the initial causes).leaf_events(): events with no successors (the final effects).causal_chain(a, b): returns a list of events forming a path fromatob, orNoneif no path exists.events_by_name(name): returns all events matching the given name.events_by_source(source): returns all events from a given source.slice(after, before): returns events within a causal window.
causal_depth() measures the longest chain of causal edges, not the number of
events. A computation with three events in a linear chain (A causes B causes C) has a causal
depth of 2.Clock Management
Computations automatically manage logical clocks. When you record an event, the computation advances its internal clock and associates a logical timestamp with the event. This allows precise temporal reasoning even in distributed settings where wall-clock time is unreliable.
comp = Computation()
e = Event(name="tick", source="scheduler")
comp.record(e)
# Access the logical timestamp assigned to the event
ts = comp.timestamp(e)
print(ts) # Logical clock value
Filtering and Slicing
For large computations, you can extract subsets of interest without copying the entire graph:
# All events from the "worker" source
worker_events = comp.events_by_source("worker")
# Events causally between e1 and e3
window = comp.slice(after=e1, before=e3)
# All events with a specific name
starts = comp.events_by_name("start")
To define the event vocabulary that components can produce and consume, see Interfaces and Actions.