Sequences
The sequences module defines AMBER’s vectorized view API. The full
population lives at model.agents; filtered and scatter views are
produced by where / indexing / at[...]. All three view types share
the same attribute/assignment protocol — column reads return Polars Series
sourced from model.agents_df on CPU, and column writes go through
Model._set_frame (contract-observed when enabled).
Under model.gpu().run() (0.4.4), numeric columns are device-resident
for the vectorized step body; the same where / column assign /
scatter_add idiom applies. Host Polars is synced at step boundaries when
the contract or reporters need a CPU snapshot. agents.array(...) is
flagged as uncertified_mutable_borrow when the contract is on.
Canonical operations on a view:
Read —
view.col,view.numpy('x', 'y'),view.frame/view.idsWrite —
view.col = values,view.set(x=…, y=…)(atomic multi-column)Reduce —
view.scatter_add(col=delta)(duplicate ids sum)Tensor —
view.borrow(col)/view.commit(**cols)
Prefer these over Model.update_agent_data / batch_update_agents and
Population.set_agent_value / batch_update* (deprecated aliases).
AgentList
- class ambr.AgentList(model: Model, agents_or_n: List[Agent] | int = None, agent_type: Type[Agent] | None = None)[source]
Bases:
_BaseViewFull view over a model’s population. Lives at
model.agents.- property agent_ids
Deprecated alias for
ids.
- borrow(column: str)[source]
Zero-copy, read-only borrow of a numeric column for tensor kernels.
Returns
(array, is_view); pair withcommit(). Seeambr.tensor_lanefor the snapshot-view contract on borrow/commit.
- by_id(agent_id) Agent[source]
Return the tracked Agent object with this id (the per-agent / OOP lane).
Lets per-agent code reach another agent without a hand-rolled id->object dict (
add_agents(n, agent_class=...)tracks the objects for you).
- commit(**columns: Any) None[source]
Atomically write back derived columns (the tensor-lane commit path).
agents.commit(x=nx, y=ny). Routes throughcommit_columnsso the snapshot-view contract observes the writes.
- property frame: DataFrame
Read-only snapshot of the full agent table (alias for
model.agents_df).
The full population view. Lives at model.agents and acts as both the
entry point for vectorized queries and a legacy list of Agent objects.
Vectorized usage (preferred):
# Filter by predicate and update columnar state
rich = model.agents.where(model.agents.wealth > 100)
rich.tag = 'rich'
# Scatter-add deltas for random id draws (duplicates sum correctly)
recipients = model.rng.choice(model.agents.ids.to_numpy(), size=50)
model.agents.at[recipients].scatter_add(wealth=1)
Legacy list usage (still supported):
# Indexing, iteration, append/remove — works as before
first = model.agents[0]
for agent in model.agents:
agent.step()
model.agents.append(new_agent)
FilteredAgentList
- class ambr.sequences.FilteredAgentList(model: Model, ids: Series, parent: AgentList)[source]
Bases:
_SubViewSubset view produced by
agents.where(...)/agents[mask].
Returned from model.agents.where(...) or model.agents[mask].
Operates on the subset of rows matching a predicate. Writing to a column
on this view touches only the filtered agents.
ScatterAgentList
- class ambr.sequences.ScatterAgentList(model: Model, ids: Series, parent: AgentList)[source]
Bases:
_SubViewId-indexed view produced by
agents.at[ids](ids may repeat).
Returned from model.agents.at[ids]. Unlike a filtered view, a scatter
view can contain duplicate ids — which is the whole point for “random
recipient” style updates. Use scatter_add to accumulate deltas when
ids repeat; plain assignment falls back to last-write-wins semantics.
Features
DataFrame-backed attribute reads and writes — no sync gotchas.
Predicate filtering via
where(...)with attribute predicates or raw Polars expressions.Scatter-add for flow-of-resources updates.
Full back-compat with legacy list-style access (indexing, iteration,
append/remove,call/apply).