A Go library for Petri net modeling, ODE simulation, process mining, and predictive monitoring.
Port of the JavaScript pflow.xyz library with additional features:
- Learn process models from event logs
- Predict case completion times in real-time
- Fit parameters using Neural ODE-ish approaches
- Continuous state machine operation with triggers
New to go-pflow? Start here:
- Installation - Get up and running in 2 minutes
- Quick Start - Your first simulation
- 📚 Documentation Hub - Comprehensive learning materials
- 🎯 Examples - Working demos and tutorials
Looking for something specific?
- Package Reference - API documentation
- CLI Tool - Command-line interface
- Process Mining - Learn from event logs
- Architecture - System design
- Petri Net Modeling: Define places, transitions, and arcs with fluent Builder API
- JSON Import/Export: Load and save Petri nets in JSON-LD format compatible with pflow.xyz
- ODE Simulation: Convert Petri nets to ODEs using mass-action kinetics with multiple solvers (Tsit5, RK45, implicit methods)
- Equilibrium Detection: Automatic steady-state detection with configurable tolerances
- Workflow Framework: Task dependencies, resource management, SLA tracking, and case monitoring
- State Machine Engine: Hierarchical states, parallel regions, guards, and actions compiled to Petri nets
- Actor Model: Message-passing actors with Petri net behaviors, signal bus, and middleware
- Reachability Analysis: State space exploration, deadlock detection, liveness analysis, P-invariants
- Sensitivity Analysis: Parameter impact ranking, gradient computation, grid search optimization
- Hypothesis Evaluation: Parallel move evaluation for game AI and decision making
- Caching: Memoization for repeated simulations with LRU eviction
- Process Discovery: Alpha Miner and Heuristic Miner algorithms
- Rate Learning: Learn transition rates from event log timing data
- Predictive Monitoring: Real-time case tracking with SLA prediction and alerting
- Neural ODE-ish Learning: Fit learnable transition rates to observed data
- SVG Visualization: Petri nets, workflows, state machines, and simulation plots
go get github.com/pflow-xyz/go-pflowpackage main
import (
"fmt"
"github.com/pflow-xyz/go-pflow/petri"
"github.com/pflow-xyz/go-pflow/solver"
"github.com/pflow-xyz/go-pflow/plotter"
)
func main() {
// Create a simple Petri net: A -> B
net := petri.NewPetriNet()
net.AddPlace("A", 100.0, nil, 0, 0, nil)
net.AddPlace("B", 0.0, nil, 0, 0, nil)
net.AddTransition("convert", "default", 0, 0, nil)
net.AddArc("A", "convert", 1.0, false)
net.AddArc("convert", "B", 1.0, false)
// Set up simulation
initialState := net.SetState(nil)
rates := map[string]float64{"convert": 0.1}
prob := solver.NewProblem(net, initialState, [2]float64{0, 20}, rates)
// Solve
sol := solver.Solve(prob, solver.Tsit5(), solver.DefaultOptions())
// Plot results
svg, _ := plotter.PlotSolution(sol, nil, 800, 600,
"A → B Conversion", "Time", "Amount")
fmt.Println("Final state:", sol.GetFinalState())
// Save SVG...
}Comprehensive documentation for learning and reference:
Learn the fundamentals and build real systems:
- Documentation Hub - Complete learning path for undergraduates and practitioners
- Petri Nets Explained - What they are and why we use them
- ODE Simulation - Why differential equations for discrete systems
- Process Mining - Discover processes from event logs
- Predictive Monitoring - Real-time prediction and SLA detection
- Getting Started Tutorial - Your first working system
- Mathematics Reference - Equations, derivations, and theory
Detailed API and implementation documentation:
- eventlog - Event log parsing, analysis, and statistics
- mining - Process discovery and rate learning from logs
- monitoring - Real-time case tracking and prediction
- schema - JSON format specifications and validation
- pflow CLI - Command-line tool for simulation, analysis, and plotting
- AI-native design for seamless integration with assistants
- Structured JSON output optimized for machine consumption
- Full simulation, analysis, and visualization pipeline
- CLAUDE.md - Comprehensive guide for AI assistants (Claude, etc.)
- Evolutionary development approach (logs → mining → validation → features)
- When to use Petri nets for different problem types
- Problem-specific patterns (games, optimization, constraints, epidemics)
- Solver tuning and performance optimization
- Code templates and idioms
- ROADMAP - Development status, completed features, and future plans
- ACCOMPLISHMENTS - Key achievements and milestones
- RESEARCH PAPER OUTLINE - Academic context and contributions
- PROCESS MINING DIRECTIONS - Process mining methodology and approach
Complete working demonstrations organized by complexity and purpose. See examples/README.md for detailed comparisons and teaching progression.
examples/basic/ - Foundation concepts
- Simple workflow and producer-consumer patterns
- Sequential token flow and resource management
- Your first Petri net simulation
- Run:
cd examples/basic && go run main.go
examples/coffeeshop/ - Comprehensive demo ⭐
- Actor pattern for high-level orchestration
- Petri nets for inventory management
- Workflows for order processing with SLAs
- State machines for equipment/staff/customer states
- ODE simulation for capacity planning
- Process mining for analyzing event logs
- Run:
cd examples/coffeeshop/cmd && go run main.go
examples/eventlog_demo/ - Event log analysis
- Parse CSV event logs
- Extract timing statistics
- Analyze process behavior
- Run:
cd examples/eventlog_demo && go run main.go
examples/mining_demo/ - Process discovery
- Discover process models from logs
- Learn transition rates automatically
- Compare discovered vs actual behavior
- Run:
cd examples/mining_demo && go run main.go
examples/monitoring_demo/ - Real-time prediction ⭐
- Live case tracking and prediction
- SLA violation detection with advance warning
- Complete hospital patient flow example
- Run:
cd examples/monitoring_demo && go run main.go
examples/incident_simulator/ - IT incident management
- Simulate incident lifecycle (detection → resolution)
- Predict completion times and SLA violations
- Real-world IT operations example
- See REGRESSION_TEST_EXPLAINED.md
examples/neural/ - Neural ODE-ish learning
- Fit learnable rates to observed data
- A → B decay with rate recovery
- SIR model with multiple learnable parameters
- Compare true vs fitted trajectories
- Run:
cd examples/neural && go run main.go
examples/dataset_comparison/ - Model calibration
- Fit models to real-world datasets
- Compare different parameterizations
- Validate model accuracy
examples/tictactoe/ - Perfect play game AI
- Minimax algorithm with ODE-based evaluation
- Game tree exploration
- Pattern recognition for win detection
- Compare strategies: random, pattern, minimax, ODE
- Complexity: 5,478 legal positions, solved game
- Run:
cd examples/tictactoe && go run ./cmd
examples/nim/ - Optimal game strategy
- Discrete state space modeling
- Optimal strategy based on Grundy numbers
- ODE-based position evaluation
- Complexity: Linear chain, provably optimal
- Run:
cd examples/nim && go run ./cmd
examples/connect4/ - Complex pattern recognition
- 69 window patterns per board state
- Threat detection and blocking
- Lookahead search (minimax-lite)
- Complexity: ~10^13 legal positions, 130 places, 222 transitions
- Petri Net Model: Full board state + win detection in net structure
- See MODEL_EVOLUTION.md
- Run:
cd examples/connect4 && go run ./cmd
examples/sudoku/ - Constraint satisfaction modeling
- Sudoku rules as Petri net structure
- Constraint propagation via transitions
- ODE analysis for solution detection
- Colored Petri nets for digit representation
- See ODE_ANALYSIS.md
- Run:
cd examples/sudoku/cmd && go run *.go
examples/chess/ - Classic chess problems ⭐
- N-Queens: Place queens without attacks (backtracking + ODE)
- Knight's Tour: Hamiltonian path with Warnsdorff heuristic
- N-Rooks: Permutation matrix placement
- ODE-based move evaluation with optimized solver parameters
- See examples/chess/README.md
- Run:
cd examples/chess/cmd && go run *.go --problem=queens
examples/knapsack/ - Combinatorial optimization
- 0/1 knapsack problem as Petri net with mass-action kinetics
- Transition rates encode value/weight efficiency preferences
- Exclusion analysis: disable items to measure sensitivity
- Continuous relaxation of discrete optimization
- Same pattern as game move evaluation (disable → observe)
- Run:
cd examples/knapsack/cmd && go run *.go
examples/visualization_demo/ - SVG generation demo
- Petri net visualizations (SIR model, producer-consumer)
- Workflow diagrams (approval, parallel, incident management)
- State machine diagrams (traffic light, order status, media player)
- Run:
make run-visualization
- examples/VISUALIZATIONS.md - Gallery of visualization examples
- examples/FEATURE_REVIEW.md - Feature comparison across examples
- examples/PARITY_STATUS.md - Implementation status matrix
| Example | Type | Complexity | Key Concepts | Best For Learning |
|---|---|---|---|---|
| basic | Workflow | Simple | Token flow, sequential processes | Petri net fundamentals |
| coffeeshop | Integration | Complex | Actors, workflows, state machines, mining | All features together ⭐ |
| eventlog_demo | Analysis | Simple | CSV parsing, statistics | Event log basics |
| mining_demo | Discovery | Medium | Process discovery, rate learning | Process mining |
| monitoring_demo | Real-time | Medium | Prediction, SLA detection | Production systems ⭐ |
| incident_simulator | Operations | Medium | IT workflows, SLA prediction | Real-world processes |
| neural | ML | Medium | Parameter fitting, learning | Data-driven modeling |
| dataset_comparison | Calibration | Medium | Model fitting, validation | Model selection |
| tictactoe | Game AI | Medium | Minimax, perfect play | Game theory |
| nim | Game Theory | Medium | Optimal strategy, discrete states | Mathematical modeling |
| connect4 | Game AI | Complex | Pattern recognition, lookahead | Advanced AI techniques |
| sudoku | Puzzle | Medium | Constraint satisfaction, colored nets | CSP modeling |
| chess | Puzzle/AI | Complex | N-Queens, Knight's Tour, ODE heuristics | Classic algorithms ⭐ |
| knapsack | Optimization | Medium | Mass-action kinetics, exclusion analysis | Combinatorial optimization |
| visualization_demo | Visualization | Simple | SVG rendering, workflows, state machines | Model documentation |
Comprehensive API reference for each package:
Defines the fundamental building blocks with both explicit and fluent APIs:
// Explicit construction
net := petri.NewPetriNet()
net.AddPlace("p1", initialTokens, capacity, x, y, labelText)
net.AddTransition("t1", role, x, y, labelText)
net.AddArc(source, target, weight, inhibitTransition)
// Fluent Builder API
net := petri.Build().
Place("S", 999).Place("I", 1).Place("R", 0).
Transition("infect").Transition("recover").
Arc("S", "infect", 1).Arc("I", "infect", 1).Arc("infect", "I", 2).
Arc("I", "recover", 1).Arc("recover", "R", 1).
Done()
// With rates
net, rates := petri.Build().
SIR(999, 1, 0).
WithCustomRates(map[string]float64{"infect": 0.3, "recover": 0.1})Key types:
Place- State locations that hold tokensTransition- Events that consume/produce tokensArc- Directed connections between places and transitionsPetriNet- Complete net structureBuilder- Fluent API for net construction
Load and save Petri nets in pflow.xyz JSON format:
// Import
net, err := parser.FromJSON(jsonData)
// Export
jsonData, err := parser.ToJSON(net)Converts Petri nets to ODEs using mass-action kinetics and solves them:
// Create problem
prob := solver.NewProblem(net, initialState, [2]float64{t0, tf}, rates)
// Solve with Tsit5 (5th order adaptive Runge-Kutta)
sol := solver.Solve(prob, solver.Tsit5(), solver.DefaultOptions())
// Access results
finalState := sol.GetFinalState()
timeSeries := sol.GetVariable("place_name")Solver options:
Dt- Initial time step (default: 0.01)Dtmin/Dtmax- Step size boundsAbstol/Reltol- Error tolerancesAdaptive- Enable adaptive stepping (default: true)
Generate publication-ready SVG plots:
// Create plotter
p := plotter.NewSVGPlotter(800, 600)
p.SetTitle("My Plot").SetXLabel("Time").SetYLabel("Concentration")
p.AddSeries(xData, yData, "Series 1", "#ff0000")
// Render
svg := p.Render()
// Or use convenience function
svg, plotData := plotter.PlotSolution(sol, variables, 800, 600,
title, xlabel, ylabel)For continuous simulation with condition-based triggers:
// Create engine
engine := engine.NewEngine(net, initialState, rates)
// Add rules
engine.AddRule("alert_high",
engine.ThresholdExceeded("place_name", 100.0),
func(state map[string]float64) error {
fmt.Println("Threshold exceeded!")
return nil
},
)
// Run continuous simulation
ctx := context.Background()
engine.Run(ctx, 100*time.Millisecond, 0.1) // interval, dt
defer engine.Stop()
// Or run batch simulation
sol := engine.Simulate(duration, opts)Condition helpers:
ThresholdExceeded(place, value)- Trigger when value exceeds thresholdThresholdBelow(place, value)- Trigger when value falls belowAllOf(...conditions)- Combine with ANDAnyOf(...conditions)- Combine with OR
Parse, analyze, and extract insights from event logs:
// Load event log from CSV
log, err := eventlog.LoadFromCSV("data.csv")
// Get statistics
stats := log.Statistics()
fmt.Printf("Cases: %d, Events: %d\n", stats.NumCases, stats.NumEvents)
// Extract timing information
timings := eventlog.ExtractTimings(log)Full documentation: eventlog/README.md
Discover process models and learn parameters from event logs:
// Discover process model
net, err := mining.DiscoverProcess(log, mining.CommonPathMethod)
// Learn transition rates from timing data
rates := mining.LearnRates(net, timings)
// Create runnable simulation
prob := solver.NewProblem(net, initialState, timespan, rates)
sol := solver.Solve(prob, solver.Tsit5(), solver.DefaultOptions())Discovery methods:
CommonPathMethod- Find most common execution pathSequentialMethod- Sequential activity orderingGraphBasedMethod- Graph-based discovery (planned)
Full documentation: mining/README.md
Track live cases and predict completion times:
// Create monitor
monitor := monitoring.NewMonitor(net, rates)
// Add SLA rules
monitor.AddSLARule("4-hour-rule", 4*time.Hour,
func(caseID string, prediction monitoring.Prediction) {
fmt.Printf("Case %s predicted to violate SLA\n", caseID)
})
// Process incoming events
monitor.ProcessEvent(event)
// Get predictions for active cases
predictions := monitor.GetPredictions()Full documentation: monitoring/README.md
Fit learnable transition rates to observed data while keeping the Petri net structure as a prior:
// Create learnable rate functions
rf := learn.NewLinearRateFunc([]string{}, []float64{0.05}, false, false)
learnProb := learn.NewLearnableProblem(
net, initialState, [2]float64{0, 30},
map[string]learn.RateFunc{"convert": rf},
)
// Prepare observed data
times := learn.GenerateUniformTimes(0, 30, 16)
data, _ := learn.NewDataset(times, map[string][]float64{
"A": observedA,
"B": observedB,
})
// Fit parameters to minimize loss
opts := learn.DefaultFitOptions()
opts.Method = "nelder-mead"
result, _ := learn.Fit(learnProb, data, learn.MSELoss, opts)
fmt.Printf("Fitted rate: %.4f\n", result.Params[0])
fmt.Printf("Final loss: %.4f\n", result.FinalLoss)Key types:
RateFunc- Interface for learnable rate functionsLinearRateFunc- Linear model:k = θ₀ + Σᵢ θᵢ * state[placeᵢ]MLPRateFunc- Small MLP with one hidden layerLearnableProblem- ODE problem with learnable ratesDataset- Observed trajectories for trainingLossFunc- Loss function (MSE, RMSE, etc.)
Optimization methods:
nelder-mead- Nelder-Mead simplex algorithm (default)coordinate-descent- Simple coordinate descent
See examples/neural/ for complete examples including SIR model parameter recovery.
Helper functions for working with state maps:
import "github.com/pflow-xyz/go-pflow/stateutil"
// Copy and modify state
newState := stateutil.Copy(state)
newState := stateutil.Apply(state, map[string]float64{"A": 10, "B": 0})
// Analyze state
total := stateutil.Sum(state)
active := stateutil.NonZero(state)
changes := stateutil.Diff(before, after)
// Compare states
if stateutil.Equal(s1, s2) { /* identical */ }
if stateutil.EqualTol(s1, s2, 1e-6) { /* within tolerance */ }Evaluate hypothetical moves and find optimal decisions:
import "github.com/pflow-xyz/go-pflow/hypothesis"
// Create evaluator with scoring function
eval := hypothesis.NewEvaluator(net, rates, func(final map[string]float64) float64 {
return final["wins"] - final["losses"]
}).WithOptions(solver.FastOptions())
// Find best move from candidates
moves := []map[string]float64{
{"pos0": 0, "_X0": 1},
{"pos1": 0, "_X1": 1},
}
bestIdx, bestScore := eval.FindBestParallel(currentState, moves)
// Sensitivity analysis
impact := eval.SensitivityImpact(state) // Which transitions matter most?Analyze how parameters affect outcomes:
import "github.com/pflow-xyz/go-pflow/sensitivity"
// Create analyzer
scorer := sensitivity.DiffScorer("wins", "losses")
analyzer := sensitivity.NewAnalyzer(net, state, rates, scorer)
// Rank parameters by impact
result := analyzer.AnalyzeRatesParallel()
for _, r := range result.Ranking {
fmt.Printf("%s: %+.2f impact\n", r.Name, r.Impact)
}
// Grid search optimization
grid := sensitivity.NewGridSearch(analyzer).
AddParameterRange("infect", 0.1, 0.5, 5).
AddParameterRange("recover", 0.05, 0.2, 5)
best := grid.Run()Memoize repeated simulations for performance:
import "github.com/pflow-xyz/go-pflow/cache"
// State cache for full solutions
stateCache := cache.NewStateCache(1000)
sol := stateCache.GetOrCompute(state, func() *solver.Solution {
return solver.Solve(prob, solver.Tsit5(), opts)
})
// Score cache for game AI (lighter weight)
scoreCache := cache.NewScoreCache(10000)
score := scoreCache.GetOrCompute(state, computeScore)
// Check hit rate
stats := stateCache.Stats()
fmt.Printf("Hit rate: %.1f%%\n", stats.HitRate*100)Analyze discrete state space properties:
import "github.com/pflow-xyz/go-pflow/reachability"
// Create analyzer
analyzer := reachability.NewAnalyzer(net).
WithMaxStates(10000)
// Full analysis
result := analyzer.Analyze()
fmt.Printf("States: %d, Bounded: %v, Live: %v\n",
result.StateCount, result.Bounded, result.Live)
fmt.Printf("Deadlocks: %d, Dead transitions: %v\n",
len(result.Deadlocks), result.DeadTrans)
// Path finding
if analyzer.IsReachable(target) {
path := analyzer.PathTo(target)
}
// Invariant analysis
invAnalyzer := reachability.NewInvariantAnalyzer(net)
if invAnalyzer.CheckConservation(initial) {
fmt.Println("Net conserves total tokens")
}Build and execute workflows with task dependencies:
import "github.com/pflow-xyz/go-pflow/workflow"
// Build workflow with fluent API
wf := workflow.New("approval").
Name("Document Approval").
Task("submit").Name("Submit").Manual().Duration(5*time.Minute).Done().
Task("review").Name("Review").Manual().Duration(30*time.Minute).Done().
Task("decide").Name("Approve?").Decision().Done().
Task("approved").Name("Approved").Automatic().Done().
Task("rejected").Name("Rejected").Automatic().Done().
Connect("submit", "review").
Connect("review", "decide").
Connect("decide", "approved").
Connect("decide", "rejected").
Start("submit").
End("approved", "rejected").
Build()
// Execute workflow
engine := workflow.NewEngine(wf)
caseID := engine.StartCase(nil)
engine.CompleteTask(caseID, "submit", nil)Build state machines that compile to Petri nets:
import "github.com/pflow-xyz/go-pflow/statemachine"
// Build state machine
chart := statemachine.NewChart("traffic_light").
Region("light").
State("red").Initial().
State("yellow").
State("green").
EndRegion().
When("timer").In("light:red").GoTo("light:green").
When("timer").In("light:green").GoTo("light:yellow").
When("timer").In("light:yellow").GoTo("light:red").
Build()
// Create machine and process events
machine := statemachine.NewMachine(chart)
machine.SendEvent("timer") // red -> green
machine.SendEvent("timer") // green -> yellow
// Get underlying Petri net
net := chart.ToPetriNet()Build actor systems with Petri net behaviors:
import "github.com/pflow-xyz/go-pflow/actor"
// Build actor system
system := actor.NewSystem("my-system").
DefaultBus().
Actor("processor").
Name("Data Processor").
State("count", 0).
Handle("data.in", func(ctx *actor.ActorContext, s *actor.Signal) error {
count := ctx.GetInt("count", 0)
ctx.Set("count", count+1)
ctx.Emit("data.out", map[string]any{"processed": true})
return nil
}).
Done().
Start()
// Publish signals
system.Bus().Publish(&actor.Signal{
Type: "data.in",
Payload: map[string]any{"value": 42},
})Generate SVG visualizations for models:
import "github.com/pflow-xyz/go-pflow/visualization"
// Render Petri net
err := visualization.SaveSVG(net, "model.svg")
// Render workflow
err := visualization.SaveWorkflowSVG(workflow, "workflow.svg", nil)
// Render state machine
err := visualization.SaveStateMachineSVG(chart, "statemachine.svg", nil)Comprehensive test coverage across all packages:
# Run all tests
go test ./...
# Run with coverage
go test ./... -cover
# Verbose output
go test ./... -v
# Test specific package
go test ./learn/... -vExample: Test the learn package with verbose output:
go test ./learn/... -v
# All 16 tests pass with 72.7% coveragego-pflow includes a complete process mining pipeline:
Event Logs → Process Discovery → Rate Learning → Simulation → Monitoring
// 1. Load event log
log, _ := eventlog.LoadFromCSV("patient_flow.csv")
// 2. Discover process model
net, _ := mining.DiscoverProcess(log, mining.CommonPathMethod)
// 3. Learn transition rates
timings := eventlog.ExtractTimings(log)
rates := mining.LearnRates(net, timings)
// 4. Create simulation
prob := solver.NewProblem(net, initialState, timespan, rates)
sol := solver.Solve(prob, solver.Tsit5(), solver.DefaultOptions())
// 5. Set up real-time monitoring
monitor := monitoring.NewMonitor(net, rates)
monitor.AddSLARule("4-hour", 4*time.Hour, alertHandler)- Process Discovery: Automatically discover process models from event logs
- Timing Analysis: Extract activity durations and inter-arrival times
- Rate Learning: Learn transition rates from historical data
- Prediction: Forecast case completion times in real-time
- SLA Monitoring: Detect violations with 6+ hours advance warning
See examples/monitoring_demo/ for complete hospital patient flow example.
The library is designed with modularity and layered abstractions:
petri/ Core data structures (places, transitions, arcs)
├── parser/ JSON serialization (compatible with pflow.xyz)
├── solver/ ODE solvers (Tsit5, RK45, implicit methods)
├── stateutil/ State manipulation utilities
├── learn/ Neural ODE-ish learnable rates
├── plotter/ SVG plot generation
├── engine/ Continuous simulation with triggers
│
Higher-Level Abstractions
├── workflow/ Task dependencies, resources, SLA tracking
├── statemachine/ Hierarchical states compiled to Petri nets
├── actor/ Message-passing actors with Petri net behaviors
│
Analysis & Optimization
├── reachability/ State space analysis, deadlock detection
├── sensitivity/ Parameter impact analysis, grid search
├── hypothesis/ Move evaluation for game AI
├── cache/ Memoization for repeated simulations
│
Process Mining
├── eventlog/ Event log parsing and analysis
├── mining/ Alpha Miner, Heuristic Miner, rate learning
├── monitoring/ Real-time case tracking and prediction
│
Visualization
├── visualization/ SVG rendering for nets, workflows, state machines
└── plotter/ Time series plots
cmd/pflow/ Command-line interface
examples/ Working demonstrations
docs/ Learning materials
Data Flow:
Historical Data Real-Time Data
↓ ↓
Event Logs → Process Discovery ← Domain Knowledge
↓ ↓
Timing Analysis → Petri Net Model
↓ ↓
Rate Learning → ODE Simulation → Prediction
↓
Monitoring Engine → Alerts & Actions
The solver converts Petri nets to ODEs using mass-action kinetics:
For a transition T with:
- Input places:
P1, P2, ...with arc weightsw1, w2, ... - Output places:
Q1, Q2, ...with arc weightsv1, v2, ... - Rate constant:
k
The flux is: flux = k * [P1] * [P2] * ...
And derivatives:
d[Pi]/dt -= flux * wi(consume from inputs)d[Qj]/dt += flux * vj(produce to outputs)
The learn package extends the traditional ODE simulation with data-driven parameter learning:
Key Idea: The Petri net defines the structural prior (topology, mass conservation, reaction stoichiometry), while the transition rates become learnable functions k_θ(state, t) that can be fitted to observed data.
Benefits:
- Physical constraints preserved: Mass conservation, non-negativity, reaction structure
- Data-driven rates: Learn complex rate laws from observations
- Same reliable solver: Uses the existing Tsit5 adaptive integrator
- No external dependencies: Gradient-free optimization (Nelder-Mead, coordinate descent)
Use cases:
- System identification: Recover unknown rate constants from experimental data
- Model calibration: Fit parameters to match real-world trajectories
- Hybrid modeling: Combine known structure with learned components
- Adaptive control: Learn dynamics online for feedback systems
Design:
RateFuncinterface allows custom rate laws (linear, MLP, or user-defined)LearnableProblemwrapssolver.Problemwith parameterized ratesFit()optimizes parameters to minimize loss on observed data- Fully compatible with existing
solverandpetriAPIs
This approach bridges mechanistic modeling (Petri nets) with machine learning, enabling interpretable models that respect physical laws while learning from data.
Active development focuses on:
- Engine package: Real-time state monitoring, event-driven actions, feedback control systems
- Learn package: Adjoint-based gradients, online learning, uncertainty quantification
- Monitoring package: Multi-case optimization, adaptive interventions, what-if scenarios
See ROADMAP.md for detailed development plans, priorities, and completed features.
This technology applies to any process with:
- Multiple steps - Registration, triage, processing, completion
- Timing constraints - SLAs, deadlines, service levels
- Historical data - Event logs with timestamps
- Need for prediction - Will this be late? When will it complete?
Application Domains:
- Healthcare: Patient flow, surgery scheduling, bed management, ER throughput
- Manufacturing: Production lines, quality control, delivery prediction
- Logistics: Order fulfillment, shipping, warehouse operations
- Finance: Loan processing, fraud investigation, compliance workflows
- IT Operations: Incident management, service requests, deployment pipelines
- Government: Permit processing, case management, citizen services
See examples/monitoring_demo/ for hospital patient flow and examples/incident_simulator/ for IT incident management.
- Go 1.23.6 or later
- JSON format compatible with pflow.xyz
- Portable - no external dependencies
MIT License - see LICENSE for details.
Based on the public domain implementation from pflow.xyz.
Contributions welcome! Areas for improvement:
- Additional ODE solvers (Euler, RK4, etc.)
- Performance optimizations for large nets
- Additional visualization options
- More example models and use cases
- Enhanced engine capabilities
- Process mining algorithms (Alpha, Heuristics, Inductive)
- Additional monitoring and prediction features
See ACCOMPLISHMENTS.md for recent achievements and ROADMAP.md for planned features.
- pflow.xyz - Original JavaScript implementation and online editor
- RESEARCH_PAPER_OUTLINE.md - Academic context and research contributions
- PROCESS_MINING_DIRECTIONS.md - Process mining methodology
- Tsitouras, Ch. "Runge-Kutta pairs of order 5(4)..." Computers & Mathematics with Applications, 62 (2011) 770-775