SciML Integration

using AlgebraicAgents
# declare problems (models in AA's type system)
using DifferentialEquations

# vanilla function
f(u,p,t) = 1.01*u
u0 = 1/2
tspan = (0.0,10.0)
prob = ODEProblem(f,u0,tspan)
ODEProblem with uType Float64 and tType Float64. In-place: false
timespan: (0.0, 10.0)
u0: 0.5

Atomic Models

m1 = DiffEqAgent("model1", prob)
m2 = DiffEqAgent("model2", prob)
m3 = DiffEqAgent("model3", prob)

# declare observables (out ports) for a model
# it will be possible to reference m3's first variable as both `o1`, `o2`
push!(observables(m3), "o1" => 1, "o2" => 1)

# simple function, calls to which will be scheduled during the model integration
custom_function(agent, t) = println("inside $agent at time $t")

# a bit more intricate logic -
function f_(u,p,t)
    # access the wrapping agent (hierarchy bond)
    agent = extract_agent(p)

    # access observables
    o1 = getobservable(getagent(agent, "../model3"), "o1")
    o2 = getobservable(getagent(agent, "../model3"), "o2")
    # fetch observable's value at **a given time point in the past**
    o3 = gettimeobservable(getagent(agent, "../model3"), t/2, 1)

    # schedule interaction
    # first, schedule a call to `_interact!(agent)` with priority 0
    # this is the default behavior
    poke(agent)
    # alternatively, provide a function call f(args...)
    # this will be expanded to a call f(agent, args...)
    @call agent custom_function(agent, t)

    min(2., 1.01*u + o1 + o2 + o3)
end
f_ (generic function with 1 method)

Another Atomic Model

m4 = DiffEqAgent("model4", ODEProblem(f_,u0,tspan))
agent model4 with uuid 1a413243 of type DiffEqAgent 
   custom properties:
   integrator: 
t: 0.0
u: 0.5

Hierarchical Sum of Atomic Models

m = ⊕(m1, m2; name="diagram1") ⊕ ⊕(m3, m4; name="diagram2")
agent diagram with uuid 3bb2ca1d of type FreeAgent 
   inner agents: 
    agent diagram1 with uuid dec03495 of type FreeAgent 
       inner agents: model1, model2
    agent diagram2 with uuid 84a413c6 of type FreeAgent 
       inner agents: model3, model4
# explore path-like structure of agents

# index by unix-like path
getagent(m, "diagram1/model1/")
getagent(m, "diagram1/model1")
getagent(m1, "../model2")
getagent(m1, "../../diagram2/model3")

# index by regex expression
getagent(m, r"model.*")

# index by glob expression
getagent(m, glob"**/model?/")
getagent(m, glob"**/model?"s)
4-element Vector{DiffEqAgent}:
 DiffEqAgent{name=model4, uuid=1a413243, parent=FreeAgent{name=diagram2, uuid=84a413c6, parent=FreeAgent{name=diagram, uuid=3bb2ca1d, parent=nothing}}}
 DiffEqAgent{name=model1, uuid=685016b1, parent=FreeAgent{name=diagram1, uuid=dec03495, parent=FreeAgent{name=diagram, uuid=3bb2ca1d, parent=nothing}}}
 DiffEqAgent{name=model2, uuid=bbadda4a, parent=FreeAgent{name=diagram1, uuid=dec03495, parent=FreeAgent{name=diagram, uuid=3bb2ca1d, parent=nothing}}}
 DiffEqAgent{name=model3, uuid=915dc7e7, parent=FreeAgent{name=diagram2, uuid=84a413c6, parent=FreeAgent{name=diagram, uuid=3bb2ca1d, parent=nothing}}}

Solving

sol = simulate(m)
agent diagram with uuid 3bb2ca1d of type FreeAgent 
   inner agents: 
    agent diagram1 with uuid dec03495 of type FreeAgent 
       inner agents: model1, model2
    agent diagram2 with uuid 84a413c6 of type FreeAgent 
       inner agents: model3, model4