libpetri — Coloured Time Petri Net Engine
A high-performance Coloured Time Petri Net engine with formal verification support.
Example: Racing LLM Agent Pipeline
An agent orchestration net with coloured tokens (String messages + () control
signals), three environment inputs (keystroke activity, submitted messages,
topic-change triggers), a racing pattern (deep vs quick agent with dump semantics),
explicit context assembly (optional-dependency pattern), and two-trigger
background summarization:
use *;
// Coloured places — String messages, () control signals
let keyboard = new; // raw keystroke activity
let user_message = new; // submitted full message
let topic_change = new; // tool-call summarization trigger
let composing = new; // user is currently typing
let pending = new; // raw message, not yet context-enriched
let processing = new; // active request flag
let context_ready = new; // message enriched with context
let conversation = new; // message history (accumulates)
let summary = new; // compressed history
let summarizing = new; // summarization in progress
let thinking = new; // deep result awaiting delivery
let urgency = new; // timeout signal
let response = new; // delivered response
// Typing: keystroke → user is composing; resets urgency (user is engaged)
let typing = builder
.input
.reset
.output
.timing
.priority
.action
.build;
// Receive: submitted message → AND-fork into Pending + Processing + Conversation
// resets Composing (user finished typing)
let receive = builder
.input
.reset
.output
.timing
.priority
.action
.build;
// GatherContext: reads both Conversation + Summary → fires when Summary exists (full context)
let gather_context = builder
.input
.read
.read
.output
.timing
.action
.build;
// GatherFresh: reads Conversation, inhibited by Summary → fires when Summary absent
// Standard Petri net optional-dependency pattern — exactly one fires for any marking
let gather_fresh = builder
.input
.read
.inhibitor
.output
.timing
.action
.build;
// DeepAgent: thorough analysis — consumes ContextReady, produces Thinking
let deep_agent = builder
.input
.output
.timing // window: fires between 500ms and 10s
.action
.build;
// Timeout: fires at exactly 5s — inhibited by Response (already answered) and Composing
let timeout = builder
.read
.inhibitor
.inhibitor
.output
.timing // exact: fires at precisely 5s
.action
.build;
// QuickAgent: fast fallback — consumes Processing + Urgency, reads Conversation
let quick_agent = builder
.input
.input
.read
.output
.timing
.action
.build;
// Complete: deep wins the race — consumes Thinking + Processing, inhibited by Response
let complete = builder
.input
.input
.inhibitor // inhibitor: can't fire if quick already answered
.reset // reset arc: clears any pending urgency
.output
.timing // deadline: must complete within 3s of enablement
.action
.build;
// Dump: deep loses the race — consumes Thinking, reads Response (confirms quick answered)
// no output: acts as a sink (discards the late deep result)
let dump = builder
.input
.read // read: verifies quick already answered
.timing
.action
.build;
// AutoSummarize: fires when conversation reaches ≥3 messages (at_least input)
// consumes threshold messages + resets remainder; delayed cooldown prevents churn
let auto_summarize = builder
.input // at_least: need ≥3 messages
.inhibitor
.reset // reset arc: clear remaining messages
.output
.timing // delayed: 2s cooldown
.action
.build;
// ToolSummarize: external TopicChange trigger; reads Conversation, resets it
let tool_summarize = builder
.input
.read
.inhibitor
.reset
.output
.timing
.action
.build;
// SummaryDone: summarization completes — replaces old Summary
let summary_done = builder
.input
.reset // reset arc: replace old summary
.output
.timing
.action
.build;
let net = builder
.transition
.transition
.transition
.transition
.transition
.transition
.transition
.transition
.transition
.transition
.transition
.transition
.build;
All five arc types (input, output, read, inhibitor, reset), all five timing modes (immediate, window, deadline, delayed, exact), environment places, priority scheduling, AND-fork, dump semantics, and coloured tokens.
Crate Structure
| Crate | Description |
|---|---|
| libpetri-core | Places, tokens, transitions, timing, arc types, actions |
| libpetri-event | Event store for recording execution events |
| libpetri-runtime | Bitmap-based executor (sync + async via tokio feature) |
| libpetri-export | DOT/Graphviz export pipeline |
| libpetri-verification | Formal verification (P-invariants, state class graphs, SMT) |
| libpetri-debug | WebSocket debug protocol for live net inspection |
| libpetri-docgen | Build-script helper for generating Petri net SVGs in rustdoc |
Executors
- BitmapNetExecutor — General-purpose, bitmap-based enablement checks
- PrecompiledNetExecutor — High-performance alternative with ring buffers, opcode dispatch, and two-level summary bitmaps (~3.8x faster on large nets)
Feature Flags
| Feature | Effect |
|---|---|
tokio |
Enables run_async() on both executors |
z3 |
Enables SMT-based IC3/PDR model checking |
debug |
Enables the WebSocket debug protocol module |
License
Apache-2.0