TrackingDSL
Name-driven DSL for specifying multi-agent tracking problems as time-expanded cellular sheaves. @tracking_problem declares structure first; concrete numeric values are supplied later via a context dict at resolve time. See NetworkSheaves.CellularSheafParser (the dsl.md page) for the unrelated @cellular_sheaf macro.
CellularSheaves.ControlSheaves.TrackingDSL — Module
TrackingDSLName-driven DSL for specifying multi-agent tracking problems as time-expanded cellular sheaves.
This module provides a symbolic specification language (@tracking_problem, parse_tracking_program) that decouples the structural description of a tracking scenario from the numeric values of matrices and vectors. Names are declared first; concrete values are supplied via a context dict at resolve time. The full pipeline is:
parse → validate → resolve(ctx) → lower → TrackingProblemQuickstart
using CellularSheaves
using CellularSheaves.ControlSheaves.TrackingDSL
prog = @tracking_problem begin
space(X) = R^2
space(U) = R^1
map_decl(A, X, X)
map_decl(B, U, X)
map_decl(R_y, X, X)
agent(a1; dynamics=(A,B), period=dt)
agent(a2; dynamics=(A,B), period=dt)
target(t1)
horizon(K)
times(Tall = 0:K)
consensus(c1; agents=(a1,a2), maps=(R_y,R_y), at=Tall)
track(tr1; agent=a1, target=t1, maps=(R_y,R_y), at=Tall[end])
boundary(:agent, a1; at=Tall[begin], value=x0_a1)
end
ctx = Dict{Symbol,Any}(
:K => 10,
:A => [1.0 0.0; 0.0 1.0],
:B => [0.0; 1.0;;],
:R_y => [1.0 0.0; 0.0 0.0],
:dt => 0.05,
:x0_a1 => [0.0, 0.0],
)
result = lower_tracking_program(prog, ctx)
sheaf = build_time_expanded_tracking_sheaf(result.problem)Special time references
t[begin] always resolves to 0. t[end] resolves to the value of the horizon k declared with horizon K (after K is bound in ctx). The qualifying name t is syntactic decoration and is ignored.
Sub-modules
| Sub-module | Role |
|---|---|
TrackingDSLTerm | AST node definitions and exception types |
TrackingDSLParser | @tracking_problem macro and parse_tracking_program |
TrackingDSLValidator | validate_tracking_program semantic checks |
TrackingDSLResolver | resolve_tracking_program, set_indexed!, ResolvedProgram |
TrackingDSLLowering | lower_tracking_program, LoweredTrackingProblem |
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm — Module
TrackingDSLTermAbstract data type (AST) definitions for the name-driven Tracking DSL.
The DSL allows symbolic specification of multi-agent tracking problems with late binding of numeric values via an external context dict. A TrackingProgram is the root node holding a flat list of TrackingStmt nodes. Statements cover:
- Space and map declarations (
space X = R^6,map A : X -> X) - Agent/target declarations with optional dynamics (
agent a1 dynamics (A, B) period dt) - Time declarations (
horizon K,times Tall = 0:K) - Constraints (
consensus,track,consensus_sheaf) - Boundary conditions (
boundary agent a1 at t[begin] = x0)
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.AgentDecl — Type
AgentDecl(name, dynamics_A, dynamics_B, period)Declares an agent with optional ZOH dynamics. dynamics_A and dynamics_B are map names (or nothing). period is the discretisation period name or literal.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.BoundaryConstraint — Type
BoundaryConstraint(entity_kind, entity_name, time_ref, value_ref)Pin the stalk of entity at time to the vector named value_ref.
entity_kind is :agent or :target. value_ref is either a PlainRef (named vector) or an IndexedRef (late-bound index).
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.BoundaryRef — Type
BoundaryRefA reference to a boundary value in the context dict. Either a plain name foo (unindexed) or an indexed form x[a, t] allowing late-bound agent/time indices.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.ConsensusConstraint — Type
ConsensusConstraint(name, agents, maps, time_spec)Consensus edge between a pair of agents using named restriction maps, active at the given TimeSpec.
agents is a length-2 tuple (a1, a2) of agent names. maps is a length-2 tuple (R1, R2) of map names (may be equal).
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.ConsensusSheafConstraint — Type
ConsensusSheafConstraint(name, template, agents, time_spec)Instantiate a named consensus sheaf template over a list of agents at the given times.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.HorizonDecl — Type
HorizonDecl(name)Declares the time horizon horizon K. name is the identifier (e.g. :K). The value is supplied at resolve time via the context dict (:K => 40).
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.MapDecl — Type
MapDecl(name, domain, codomain)Declares a named linear map, e.g. map A : X -> X. The domain and codomain are space names.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.SpaceDecl — Type
SpaceDecl(name, dim)Declares a named Euclidean space, e.g. space X = R^6. dim is the dimension or the name of a symbol bound to an integer.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.SpaceExpr — Type
SpaceExprA space expression describing the type of a stalk. Variants:
BaseSpace(name)— a named scalar space (e.g.Xdeclared asspace X = R^6)ProductSpace(a, b)— Cartesian producta × bDirectSumSpace(a, b)— direct suma ⊕ b
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TargetDecl — Type
TargetDecl(name)Declares a tracking target with no dynamics (pinned by boundary).
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TimeAliasDecl — Type
TimeAliasDecl(alias, ref)Declares a named single-time alias, e.g. time tcapture = 7.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TimeRef — Type
TimeRefA reference to a single point in time. Can be:
LiteralTime(n)— an integer literal (e.g.0,7)NamedTime(name)— a named time alias (e.g.tcapture)BeginTime()— the special alias resolving to0(writtent[begin]in the DSL)EndTime()— the special alias resolving tokfromhorizon(writtent[end]in the DSL)
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TimeSetDecl — Type
TimeSetDecl(name, spec)Declares a named time set, e.g. times Tall = 0:K.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TimeSpec — Type
TimeSpecDescribes the set of timesteps at which a constraint is active. Variants:
SingletonTime(t)— activate at exactly oneTimeRefTimeList(ts)— activate at an explicit list ofTimeRefsTimeRange(lo, hi)— a rangelo:hiofTimeRefsNamedTimeSet(name)— reference to a declaredtimesalias
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackConstraint — Type
TrackConstraint(name, agent, target, maps, time_spec)Tracking edge between an agent and a target using named restriction maps.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingDSLError — Type
TrackingDSLErrorSupertype for all DSL-specific errors. Every subtype carries a human-readable msg::String and, where applicable, a context field identifying the offending statement or symbol.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingDeclarationError — Type
TrackingDeclarationErrorRaised for duplicate or missing name declarations.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingDimensionMismatchError — Type
TrackingDimensionMismatchErrorRaised when matrix/vector dimensions are inconsistent.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingProgram — Type
TrackingProgram(statements)Root node of a tracking DSL program. Holds a flat list of TrackingStmt nodes in declaration order.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingStmt — Type
TrackingStmtSupertype for all top-level statements in a TrackingProgram. Use @data below for the concrete variants.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingSyntaxError — Type
TrackingSyntaxErrorRaised when a statement cannot be parsed.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingTemplateError — Type
TrackingTemplateErrorRaised when a consensus sheaf template cannot be attached.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingTimeResolutionError — Type
TrackingTimeResolutionErrorRaised when a time reference cannot be resolved.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingTypeError — Type
TrackingTypeErrorRaised when a name is used with an incompatible type.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.TrackingUnboundSymbolError — Type
TrackingUnboundSymbolErrorRaised when lowering encounters a symbol without a bound value.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLTerm.VectorDecl — Type
VectorDecl(name, space)Declares a named vector, e.g. vector x0 : X.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLParser — Module
TrackingDSLParserMLStyle-driven parser for the name-driven Tracking DSL.
Provides the @tracking_problem macro and the functional parse_tracking_program entry point. All statement forms use valid Julia syntax so that Julia's own parser tokenises the block before any DSL parsing occurs.
Grammar
Statements inside a @tracking_problem begin ... end block must be valid Julia expressions. The DSL interprets them by their leading function name:
@tracking_problem begin
# Space declaration (method-definition syntax)
space(X) = R^6
space(U) = R^2
space(Stalk) = X ⊕ U # direct sum; also X * U or X × U
# Map declaration (use map_decl to avoid shadowing Base.map)
map_decl(A, X, X) # A : X → X
map_decl(B, U, X) # B : U → X
map_decl(R_y, Stalk, R^1)
# Agent / target declarations
agent(a1; dynamics=(A,B), period=dt)
agent(a2; dynamics=(A,B), period=dt)
target(t1)
target(t2)
# Horizon
horizon(K)
# Time aliases (keyword-argument syntax)
time(tcapture = 7)
# Time sets
times(Tall = 0:K)
# Constraints
consensus(c1; agents=(a1,a2), maps=(R_y,R_y), at=Tall)
track(tr1; agent=a1, target=t1, maps=(R_z,R_z), at=Tall[end])
consensus_sheaf(cS; template=CTemplate, over=(a1,a2,a3), at=tcapture)
# Boundary conditions
boundary(:agent, a1; at=Tall[begin], value=x0_a1)
boundary(:target, t1; at=t, value=x_ref[t])
boundary(:agent, a; at=t, value=x[a,t]) # indexed reference
endTime specifications
At any at= keyword, time can be given as:
- a named time set:
at=Tall(NamedTimeSet) - begin/end of horizon:
at=t[begin](BeginTime = 0),at=t[end](EndTime = k) - a literal integer:
at=0 - a range:
at=(0:K) - an explicit list:
at=[0,3]
t[begin] and t[end] use Julia array-indexing syntax; the qualifying name t is ignored and the references resolve to 0 and the horizon value k respectively.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLParser.parse_tracking_program — Method
parse_tracking_program(block::Expr) -> TrackingProgramFunctional entry point for parsing a TrackingDSL program from a Julia Expr (as returned by Meta.quot(quote ... end)).
Returns a TrackingProgram AST without validating or resolving names. Supply numeric values via the ctx argument of resolve_tracking_program or lower_tracking_program:
prog = parse_tracking_program(quote
agent(a1; dynamics=(A,B), period=dt)
horizon(K)
times(Tall = 0:K)
end)
ctx = Dict{Symbol,Any}(:K => 40, :A => [1.0 0.0; 0.0 1.0], :B => [0.0; 1.0;;], :dt => 0.05)
resolved = resolve_tracking_program(prog, ctx)Example — indexed boundary reference
prog = parse_tracking_program(quote
agent(a1; dynamics=(A,B), period=dt)
horizon(K)
boundary(:agent, a1; at=t_pin, value=x_ref[a,t_pin])
end)
ctx = Dict{Symbol,Any}(:K => 5, :A => ..., :B => ..., :dt => 0.05, :a => 1, :t_pin => 3)
set_indexed!(ctx, :x_ref, 1, 3, [0.0, 1.0, 0.0, 0.0])
resolved = resolve_tracking_program(prog, ctx)t[begin] resolves to 0; t[end] resolves to the horizon K.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLParser.@tracking_problem — Macro
@tracking_problem begin ... endParse a TrackingDSL program and return a TrackingProgram AST.
Statements are valid Julia expressions interpreted by their leading name. Numeric values are not embedded in the program; pass them via the ctx argument of resolve_tracking_program or lower_tracking_program.
The special time references t[begin] and t[end] are built-in: t[begin] resolves to 0; t[end] resolves to the horizon value k (from horizon(K) in the program and :K in the context dict). The qualifying name t is syntactic decoration and is ignored.
Example
prog = @tracking_problem begin
space(X) = R^2
map_decl(A, X, X)
map_decl(R_y, X, X)
agent(a1; dynamics=(A,R_y), period=dt)
agent(a2; dynamics=(A,R_y), period=dt)
target(t1)
horizon(K)
times(Tall = 0:K)
consensus(c1; agents=(a1,a2), maps=(R_y,R_y), at=Tall)
track(tr1; agent=a1, target=t1, maps=(R_y,R_y), at=Tall[end])
boundary(:agent, a1; at=Tall[begin], value=x0_a1)
end
ctx = Dict{Symbol,Any}(
:K => 40,
:A => [1.0 0.0; 0.0 1.0],
:R_y => [1.0 0.0; 0.0 0.0],
:dt => 0.05,
:x0_a1 => zeros(2),
)
result = lower_tracking_program(prog, ctx)t[begin] resolves to 0; t[end] resolves to the value of K.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLValidator — Module
TrackingDSLValidatorSemantic validation for TrackingProgram ASTs.
validate_tracking_program checks:
- No duplicate declarations of the same name.
- All referenced names in constraints and boundaries are declared.
- Time sets reference declared time aliases.
- Agent dynamics reference declared maps.
- Consensus/track constraints reference declared agents/targets.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLValidator.validate_tracking_program — Method
validate_tracking_program(prog::TrackingProgram)Validate the TrackingProgram AST for semantic consistency.
Raises a TrackingDeclarationError, TrackingTypeError, or TrackingTimeResolutionError if validation fails. Returns prog unchanged on success so it can be used in a pipeline:
ctx = Dict{Symbol,Any}(:K => 5, :A => ..., :B => ..., :dt => 0.05)
lower_tracking_program(prog, ctx)Validation checks:
- No duplicate names across spaces, maps, agents, targets, time aliases, constraints.
- All names referenced in constraints exist as declarations.
t[begin]andt[end]are always valid (built-in time references).
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver — Module
TrackingDSLResolverName resolution for TrackingProgram ASTs.
Resolution produces a ResolvedProgram that contains all numeric values needed by the lowering pass. The t[begin] and t[end] time references are first-class: t[begin] resolves to 0; t[end] resolves to the value of the horizon k.
All numeric values (matrices, scalars, vectors) are supplied through an external context dict passed to resolve_tracking_program. Use set_indexed! to register indexed boundary values.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver.ResolvedAgent — Type
ResolvedAgentA fully resolved agent declaration with concrete numeric matrices.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver.ResolvedBoundary — Type
ResolvedBoundaryA single boundary condition: (vertexkind, entityindex, time, stalk_vector).
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver.ResolvedConsensus — Type
ResolvedConsensusA fully resolved consensus constraint.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver.ResolvedProgram — Type
ResolvedProgramThe output of the resolution phase. All names have been replaced by concrete numeric values.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver.ResolvedTarget — Type
ResolvedTargetA fully resolved target declaration (no dynamics).
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver.ResolvedTrack — Type
ResolvedTrackA fully resolved tracking constraint.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver.resolve_tracking_program — Method
resolve_tracking_program(prog::TrackingProgram, ctx::AbstractDict) -> ResolvedProgramResolve all symbolic names in prog to concrete numeric values using the supplied context dict ctx.
ctx maps Symbol keys to their values (scalars, matrices, vectors). Use set_indexed! to register indexed boundary values:
ctx = Dict{Symbol,Any}(
:K => 5,
:A => [1.0 0.0; 0.0 1.0],
:B => [0.0; 1.0;;],
:dt => 0.05,
)
set_indexed!(ctx, :x_ref, 1, 3, [1.0, 2.0, 0.0]) # x_ref[a=1, t=3]
resolved = resolve_tracking_program(prog, ctx)Resolution steps:
- Build value environment from
ctx. - Resolve the horizon
k. - Resolve space dimensions.
- Resolve maps to concrete matrices.
- Resolve agent dynamics.
- Resolve time specs to integer vectors.
- Resolve boundary conditions (including indexed references
x[a,t]).
Raises TrackingUnboundSymbolError if any required name is missing from ctx. Raises TrackingDimensionMismatchError for inconsistent matrix dimensions.
t[begin] resolves to 0; t[end] resolves to the value of the horizon K.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLResolver.set_indexed! — Method
set_indexed!(ctx, name, agent_val, time_val, vec)Store an indexed boundary value in ctx under the canonical key (name, agent_val, time_val). Use this to supply values for boundary conditions declared with an indexed reference like boundary(:agent, a; at=t, value=x[a,t]).
Because the key is a Tuple, ctx must support non-Symbol keys. Use Dict{Any,Any} (not Dict{Symbol,Any}) when indexed values are needed:
ctx = Dict{Any,Any}(:K => 5, :A => ..., :B => ..., :dt => 0.05, :a => 1, :t_pin => 3)
set_indexed!(ctx, :x_ref, 1, 3, [0.0, 1.0, 0.0])
resolved = resolve_tracking_program(prog, ctx)CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLLowering — Module
TrackingDSLLoweringLowers a ResolvedProgram to the concrete TrackingProblem used by MultiAgentTracking.build_time_expanded_tracking_sheaf.
The main entry points are lower_tracking_program (returns a TrackingProblem plus a boundary dictionary) and the convenience wrapper that runs the full parse → validate → resolve → lower pipeline.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLLowering.LoweredTrackingProblem — Type
LoweredTrackingProblemThe result of lowering a ResolvedProgram.
Fields:
problem: aTrackingProblemcompatible withbuild_time_expanded_tracking_sheaf.boundary:Dict{Int,Vector{Float64}}keyed by vertex IDs (as returned byagent_vertex/target_vertex).
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLLowering.lower_tracking_program — Method
lower_tracking_program(resolved::ResolvedProgram;
consensus_weight = 1.0,
tracking_weight = 1.0,
include_target_dynamics = false) -> LoweredTrackingProblemLower a ResolvedProgram to a TrackingProblem and a boundary dictionary.
The result .problem is directly usable with build_time_expanded_tracking_sheaf(result.problem).
Restrictions maps for multiple consensus constraints are combined into a single shared consensus_restriction matrix (first declared wins); use the per-constraint map from ResolvedConsensus if per-edge heterogeneity is required.
For uniform consensus with a single map pair, the map is used directly. When multiple distinct maps are present, the first is stored in TrackingProblem.consensus_restriction and applied to all consensus edges.
Example
prog = parse_tracking_program(quote
space X = R^2
map A : X -> X
map B : X -> X
map R_y : X -> X
agent a1 dynamics (A, B) period dt
agent a2 dynamics (A, B) period dt
target t1
horizon K
times Tall = 0:K
consensus c1 between (a1, a2) using (R_y, R_y) at Tall
track tr1 agent a1 target t1 using (A, A) at t[end]
boundary agent a1 at t[begin] = x0_a1
end)
ctx = Dict{Symbol,Any}(
:K => 5,
:A => [1.0 0.0; 0.0 1.0],
:B => [0.0; 1.0;;],
:R_y => [1.0 0.0; 0.0 0.0],
:dt => 0.05,
:x0_a1 => [0.0, 0.0, 0.0],
)
result = lower_tracking_program(prog, ctx)t[begin] always resolves to 0; t[end] resolves to the horizon value K.
CellularSheaves.ControlSheaves.TrackingDSL.TrackingDSLLowering.lower_tracking_program — Method
lower_tracking_program(prog::TrackingProgram, ctx::AbstractDict;
consensus_weight = 1.0,
tracking_weight = 1.0,
include_target_dynamics = false) -> LoweredTrackingProblemConvenience entry point that runs the full validate → resolve → lower pipeline in one call.
prog = parse_tracking_program(quote
space X = R^2
map_decl(A, X, X)
map_decl(B, X, X)
agent a1 dynamics (A, B) period dt
agent a2 dynamics (A, B) period dt
horizon K
times Tall = 0:K
consensus c1 between (a1, a2) using (A, A) at Tall
end)
ctx = Dict{Symbol,Any}(:K => 5, :A => I(2), :B => reshape([0.0,1.0],2,1), :dt => 0.05)
result = lower_tracking_program(prog, ctx)