Skip to content

Commit 4791a81

Browse files
Structured species
- An agent now implements a property pointing at the species. - Using `@structured` macro, it is possible to set call a custom agent constructor and assign the species. - Using `@move` macro, it is possible to reuse LHS agents on the RHS and modify their species.
1 parent 2814b14 commit 4791a81

File tree

6 files changed

+195
-74
lines changed

6 files changed

+195
-74
lines changed

src/compilers.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ end
6666

6767
reserved_names =
6868
[:t, :state, :obs, :resample, :solverarg, :take, :log, :periodic, :set_params]
69-
push!(reserved_names, :state)
7069

7170
function escape_ref(ex, species)
7271
return if ex isa Symbol
@@ -103,6 +102,15 @@ function wrap_expr(fex, species_names, prm_names, varmap)
103102
end
104103
end
105104

105+
fex = prewalk(fex) do x
106+
# here we convert the query metalanguage: @t() -> time(state) etc.
107+
if isexpr(x, :macrocall) && (macroname(x) == :transition)
108+
:transition
109+
else
110+
x
111+
end
112+
end
113+
106114
# substitute the species names with "pointers" into the state space: S -> state.u[1]
107115
fex = recursively_substitute_vars!(varmap, fex)
108116
# substitute the params names with "pointers" into the parameter space: β -> state.p[:β]
@@ -139,8 +147,8 @@ function skip_compile(attr)
139147
(string(attr) == "trans")
140148
end
141149

142-
function compile_attrs(acs::ReactionNetworkSchema, structured_species)
143-
species_names = setdiff(collect(acs[:, :specName]), structured_species)
150+
function compile_attrs(acs::ReactionNetworkSchema, structured_token)
151+
species_names = setdiff(collect(acs[:, :specName]), structured_token)
144152

145153
prm_names = collect(acs[:, :prmName])
146154
varmap = Dict([name => :(state.u[$i]) for (i, name) in enumerate(species_names)])

src/interface/agents.jl

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
export AbstractStructuredSpecies, BaseStructuredSpecies
2-
export @structured
3-
export add_structured_species!
1+
export AbstractStructuredToken, BaseStructuredToken
2+
export @structured_token
3+
export add_structured_token!
44

55
# Abstract supertype of all structured species.
6-
abstract type AbstractStructuredSpecies <: AbstractAlgebraicAgent end
6+
abstract type AbstractStructuredToken <: AbstractAlgebraicAgent end
77

88
# It comes handy to keep track of the transition the entity is assigned to (if).
99
# In general, we will probably assume that each "structured agent" type implements this field.
1010
# Otherwise, it would be possible to implement getter and setter interface and use it from within ReaDyn.
11-
@aagent FreeAgent struct BaseStructuredSpecies
11+
@aagent FreeAgent struct BaseStructuredToken
12+
species::Union{Nothing,Symbol}
1213
bound_transition::Union{Nothing,ReactiveDynamics.Transition}
14+
past_bonds::Vector{Tuple{Symbol,Float64,Transition}}
1315
end
1416

1517
# We use this to let the network know that the type is structured.
@@ -25,33 +27,45 @@ function register_structured_species!(reaction_network, type)
2527
end
2628

2729
# Convenience macro to define structured species.
28-
macro structured(network, type)
29-
name = Docs.namify(type.args[2])
30-
30+
macro structured_token(network, type)
3131
quote
3232
$(AlgebraicAgents.aagent(
33-
BaseStructuredSpecies,
34-
AbstractStructuredSpecies,
33+
BaseStructuredToken,
34+
AbstractStructuredToken,
3535
type,
3636
ReactiveDynamics,
3737
))
38-
register_structured_species!($(esc(network)), $(QuoteNode(name)))
3938
end
4039
end
4140

4241
# Add a structured agent instance to an instance of a reaction network.
43-
function add_structured_species!(problem::ReactionNetworkProblem, agent)
44-
return entangle!(getagent(problem, "structured/$(nameof(typeof(agent)))"), agent)
42+
function add_structured_token!(problem::ReactionNetworkProblem, agent)
43+
return entangle!(getagent(problem, "structured"), agent)
4544
end
4645

4746
import AlgebraicAgents
4847

4948
# By default, structured agents have no evolutionary rule.
50-
AlgebraicAgents._projected_to(::AbstractStructuredSpecies) = nothing
51-
AlgebraicAgents._step!(::AbstractStructuredSpecies) = nothing
49+
AlgebraicAgents._projected_to(::AbstractStructuredToken) = nothing
50+
AlgebraicAgents._step!(::AbstractStructuredToken) = nothing
5251

5352
# Tell if an agent is assigned to a transition, as a resource.
54-
isblocked(a) = !isnothing(a.bound_transition)
53+
isblocked(a::AbstractStructuredToken) = !isnothing(get_bound_transition(a))
54+
55+
# Add a record that an agent was used as "species" in a "transition".
56+
function add_to_log!(a::AbstractStructuredToken, species::Symbol, t, transition::Transition)
57+
return push!(a.past_bonds, (species, Float64(t), transition))
58+
end
59+
60+
# Set the transition a token is bound to.
61+
get_bound_transition(a::AbstractStructuredToken) = a.bound_transition
62+
function set_bound_transition!(a::AbstractStructuredToken, t::Union{Nothing,Transition})
63+
return a.bound_transition = t
64+
end
5565

5666
# Priority with which an unbound agent will be assigned to a transition.
57-
priority(a, transition) = 0.0
67+
priority(a::AbstractStructuredToken, transition) = 0.0
68+
69+
# What species (place) is an agent currently assigned to.
70+
get_species(a::AbstractStructuredToken) = a.species
71+
set_species!(a::AbstractStructuredToken, species::Symbol) = a.species = species

src/interface/reaction_parser.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ function recursive_find_reactants!(
6363
for i = 2:length(ex.args)
6464
recursive_find_reactants!(ex.args[i], mult, mods, reactants)
6565
end
66+
elseif isexpr(ex, :call) ||
67+
(ex.head == :macrocall && macroname(ex) [:structured, :move])
68+
push!(reactants, FoldedReactant(ex, mult, mods))
6669
elseif ex.head == :macrocall
6770
mods = copy(mods)
6871
macroname(ex) in species_modalities && push!(mods, macroname(ex))
@@ -71,8 +74,6 @@ function recursive_find_reactants!(
7174
4:length(ex.args),
7275
)
7376
recursive_find_reactants!(ex.args[3], mult, mods, reactants)
74-
elseif isexpr(ex, :call)
75-
push!(reactants, FoldedReactant(ex, mult, mods))
7677
else
7778
@error("malformed reaction")
7879
end

0 commit comments

Comments
 (0)