Pflow provides a wrapper to build out Petri-net models for Petri.jl with support for colored Petri nets and JSON-LD output format.
This wrapper makes it easier to compose Petri-nets with code, which allows faster iteration and more complex design.
See Petri.jl for more details about model analysis.
Beta - works but visualization needs polish
- Simplifies the composition of Petri-net models
- NEW: Parse JSON-LD format to construct Pflow models with
from_json() - NEW: Merge multiple models together with
merge()or+operator - NEW: Support for colored Petri nets with array-based token representations
- NEW: JSON-LD compatible output format matching pflow-xyz ecosystem
- NEW: Enhanced SVG output with CSS styling matching pflow-xyz
- Enhances SVG output for visualization in IJulia / IPython Notebooks
- Pflow models convert to html, svg, json
- Export to Petri.jl Model for analysis (colored nets automatically sum to token counts)
- Compatible with pflow.xyz/editor
Parse JSON-LD format from pflow.xyz directly into Pflow models:
json_str = """{ "@type": "PetriNet", "places": {...}, "transitions": {...} }"""
model = from_json(json_str)Supports all pflow.xyz JSON-LD fields including places, transitions, arcs, token colors, and inhibitor arcs.
Combine multiple Pflow models into one:
# Using merge function
combined = merge(model1, model2)
# Or using + operator
combined = model1 + model2Automatically handles name conflicts and preserves all model properties including token colors and inhibitor arcs.
Places, transitions, and arcs now support array-based data for colored tokens:
Place.initial:Vector{Int}for multi-color token countsPlace.capacity:Vector{Float64}for color-specific capacity limitsArc.weight:Vector{Int}for color-specific arc weightsPflow.token:Vector{String}for token color definitions (URLs or hex colors)
JSON output now includes @type fields for semantic web compatibility and matches the pflow-xyz data format.
See COLORED_PETRI_NETS.md for detailed documentation on colored nets and USAGE_GUIDE.md for JSON-LD parsing and model merging examples.
Run PFlow-jl with Jupyter notebook in a Docker container:
docker-compose upThen open your browser to the URL displayed in the terminal. See DOCKER.md for detailed instructions.
To install PFlow.jl locally, use the following command in Julia:
using Pkg
Pkg.add(PackageSpec(url="https://github.com/pflow-xyz/pflow-jl.git"))There is a compatibility issue with the Petri.jl dependency and Julia 1.12. After installation, you may need to apply a workaround. See WORKAROUND.md for details.
Here is a basic example of how to use PFlow.jl to define a simple Petri net model for solving a knapsack problem:
#
# *** Build out the Model ***
#
using PFlow: Pflow, place!, arc!, transition!, to_state, to_json, to_model, set_rates
function knapsack!(m::Pflow)
# Add places
place!(m, "item0", initial=1, x=351, y=140)
place!(m, "item1", initial=1, x=353, y=265)
place!(m, "item2", initial=1, x=351, y=417)
place!(m, "item3", initial=1, x=350, y=543)
place!(m, "weight", x=880, y=320)
place!(m, "value", x=765, y=145)
place!(m, "capacity", initial=15, x=730, y=541)
transition!(m, "txn0", x=465, y=139)
transition!(m, "txn1", x=466, y=264)
transition!(m, "txn2", x=462, y=418)
transition!(m, "txn3", x=464, y=542)
# Add arcs
arc!(m, source="txn0", target="weight", weight=2)
arc!(m, source="txn0", target="value", weight=10)
arc!(m, source="txn1", target="weight", weight=4)
arc!(m, source="item0", target="txn0", weight=1)
arc!(m, source="txn1", target="value", weight=10)
arc!(m, source="item1", target="txn1", weight=1)
arc!(m, source="item2", target="txn2", weight=1)
arc!(m, source="item3", target="txn3", weight=1)
arc!(m, source="txn2", target="weight", weight=6)
arc!(m, source="txn2", target="value", weight=12)
arc!(m, source="txn3", target="value", weight=18)
arc!(m, source="txn3", target="weight", weight=9)
arc!(m, source="capacity", target="txn0", weight=2)
arc!(m, source="capacity", target="txn1", weight=4)
arc!(m, source="capacity", target="txn2", weight=6)
arc!(m, source="capacity", target="txn3", weight=9)
end
m = Pflow()
knapsack!(m) # create the model
# Convert the model to JSON format
# NOTE: json format is compatible with pflow.xyz/editor
json_data = to_json(m)
# construct rates for transitions
rates = set_rates(m, (
:txn0 => 1.0,
:txn1 => 1.0,
:txn2 => 0.0, # disable txn2
:txn3 => 1.0
))
# calculate initial state of the model
initial_state = to_state(m)
# NOTE: Requires IJulia (run in Ipython notebook)see: ./example.ipynb
display(HTML(to_html(m))) # render the model
#
# *** Convert to ODE problem, solve and Graph ***
#
using Plots
using Petri
using LabelledArrays
using Plots
using OrdinaryDiffEq
# Convert the model to Petri.Model
petri_net = to_model(m)
time_max = 5.0
tspan = (0.0, time_max)
# convert to ODE problem
prob = ODEProblem(petri_net, initial_state, tspan, rates)
# create a solution
sol = solve(prob, Tsit5())
#graph
plot(title="Knapsack Simulation", xlabel="Time", ylabel="Tokens", lw=2)
plot!(sol.t, sol[:value, :], label="Value")
value = round(sol[:value, end], digits=3)
annotate!(4, value, text("Value: $value", 10, :left))using PFlow: from_json
# JSON-LD string from pflow.xyz
json_str = """{
"@context": "https://pflow.xyz/schema",
"@type": "PetriNet",
"@version": "1.1",
"places": {
"p1": {
"@type": "Place",
"capacity": [10],
"initial": [5],
"x": 100,
"y": 100
}
},
"transitions": {
"t1": {
"@type": "Transition",
"x": 200,
"y": 100
}
},
"arcs": [
{
"@type": "Arrow",
"source": "p1",
"target": "t1",
"weight": [1],
"inhibitTransition": false
}
],
"token": ["https://pflow.xyz/tokens/black"]
}"""
# Parse into a Pflow model
model = from_json(json_str)using PFlow: Pflow, place!, transition!, arc!, merge
# Create producer model
producer = Pflow()
place!(producer, "source", initial=10, x=50, y=100)
transition!(producer, "produce", x=100, y=100)
arc!(producer, source="source", target="produce", weight=1)
# Create consumer model
consumer = Pflow()
place!(consumer, "sink", initial=0, x=200, y=100)
transition!(consumer, "consume", x=150, y=100)
arc!(consumer, source="sink", target="consume", weight=1)
# Merge models
pipeline = merge(producer, consumer)
# Or use + operator: pipeline = producer + consumer
# The merged model contains all places, transitions, and arcs
# Name conflicts are automatically resolved with suffixesSee examples/json_and_merge_example.jl for more examples.