-
Notifications
You must be signed in to change notification settings - Fork 0
Writing Custom Programs
Samuele95 edited this page Jan 31, 2026
·
1 revision
This guide explains how to write your own aggregate programs using the computational fields framework.
An aggregate program is a Python function that takes a Context and returns a value:
from computational_fields.blocks.gradient import gradient
def my_program(ctx):
is_source = ctx.sense("is_source")
distance = gradient(ctx, is_source)
return distancefrom computational_fields.simulation.network import Network
from computational_fields.simulation.engine import SimulationEngine
# Create an 8x8 grid
net = Network.grid(
rows=8, cols=8, spacing=1.0, comm_range=1.5,
sensors_fn=lambda did, row, col: {"is_source": did == 0}
)
# Run the simulation
engine = SimulationEngine(net, my_program)
results = engine.run(num_rounds=20)Sensors are the input mechanism. Set them when creating the network:
def sensors(device_id, row, col):
return {
"is_source": device_id == 0,
"temperature": 20.0 + row * 0.5,
"is_exit": row == 0 or col == 0,
}
net = Network.grid(8, 8, sensors_fn=sensors)Read sensors in your program:
def program(ctx):
temp = ctx.sense("temperature")
return tempThe power of aggregate computing comes from composition:
from computational_fields.blocks.gradient import gradient, broadcast
from computational_fields.blocks.collection import collect
from computational_fields.blocks.sparse import sparse
def monitoring_program(ctx):
# Step 1: Elect leaders
is_leader = sparse(ctx, grain=3.0)
# Step 2: Compute distance to nearest leader
dist_to_leader = gradient(ctx, is_leader)
# Step 3: Collect temperature readings at leaders
temp = ctx.sense("temperature")
avg_temp = collect(ctx, dist_to_leader, lambda a, b: a + b, temp, 0.0)
# Step 4: Broadcast alerts from leaders
alert = broadcast(ctx, is_leader, avg_temp > 30.0)
return {"distance": dist_to_leader, "alert": alert}Return a dictionary to produce multiple named fields:
def multi_field_program(ctx):
return {
"gradient": gradient(ctx, ctx.sense("is_source")),
"leader": sparse(ctx, 3.0),
}Access individual fields from the engine:
engine.step()
gradient_field = engine.get_field("gradient")
leader_field = engine.get_field("leader")-
Always use
ctx— pass it as the first argument to every primitive and block call - Avoid side effects — programs should be pure functions of sensor inputs and neighbour state
- Think in fields — every expression produces a value on every device simultaneously
- Compose blocks — build complex behaviour by chaining G, C, S, T blocks
- Test convergence — run enough rounds for the field to stabilise (typically O(diameter))