Skip to content

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.

computation_example.py python
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 from a to b, or None if 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.
i Note
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.

clock_management.py python
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:

filtering.py python
# 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")
💡 Tip
Computations are the recommended entry point for most applications. Use Posets directly only when you need low-level control over the causal graph without clock overhead.

To define the event vocabulary that components can produce and consume, see Interfaces and Actions.