merck / algebraicagents.jl Goto Github PK
View Code? Open in Web Editor NEWA lightweight framework to enable hierarchical, heterogeneous dynamical systems co-integration. Batteries included!
License: Other
A lightweight framework to enable hierarchical, heterogeneous dynamical systems co-integration. Batteries included!
License: Other
It would be great to automatise docs deployment, add build and code coverage tests, etc. This would apply to our other projects as well.
Status:
Any agent type being made from calling @aagent
is mutable, but with Julia versions >= 1.8 now we can specify particular fields as being const
, which can help bring performance closer to immutable structs (see https://docs.julialang.org/en/v1/manual/types/#Mutable-Composite-Types). It would be nice to let users to specify fields as const
if they like, to improve performance. I'll look into how to make this work with the macros. Alternatively I can also look into how to replicate the functionality with standard functions.
Using SciML integration, it may happen that the simulation terminates before all agents have reached the final time point.
Consider
tspan = (0.0, 6.0) # try various values of `tspan[2]`
function ẋ(u,p,t)
agent = @get_agent p
y = getobservable(getagent(agent, "../agent_y"), "y")
return [p.α * y]
end
px = (α = 0.5,)
x0 = [0.1]
function ẏ(u,p,t)
agent = @get_agent p
x = getobservable(getagent(agent, "../agent_x"), "x")
return [p.β * x]
end
py = (β = 1.2,)
y0 = [1.0]
agent_x = DiffEqAgent("agent_x", ODEProblem(ẋ,x0,tspan,px), dt=0.00001)
agent_y = DiffEqAgent("agent_y", ODEProblem(ẏ,y0,tspan,py), dt=0.00001)
push_exposed_ports!(agent_x, "x" => 1)
push_exposed_ports!(agent_y, "y" => 1)
joint_system = ⊕(agent_x, agent_y; name="joint_system")
sol = AlgebraicAgents.simulate(joint_system)
In general, I propose that we change to implementation of step!
to something like
# local step implementation
(_projected_to(a) == t) && _step!(a, t)
@ret ret _projected_to(a)
so that one avoids the errors I made when implementing SciML integration.
Moreover, the implementation of @ret
has to be fixed likewise. Note that we want to find the least time point, up to which all agents were projected. Now, _projected_to(a)
returns
nothing
if the agent does not implement its evolution (e.g., wrap of embedded agents),true
if we already projected the agent to the final time point (no more calls to _step!
,@ret
shall return the least time point (or nothing
or true
). For that calculation, nothing
is an idempotent; if all agents return true
(or nothing
, but at least one is true
), then this is true
for the entire system, otherwise we take the least number returned by the _projected_to
(ingoring possible trues of some agents).
Apparently I did not update the documentation for Opera
properly. For instance, there is a mention of AbstractOperaCall
, which has been deprecated.
AlgebraicAgents.jl/docs/src/design.md
Line 35 in 022e52a
I was testing if the macros could allow us to use parameterized types for the agents when I noticed that even if there is an error when interpolating the symbols into expressions in define_agent
, the name of the new agent type will still be assigned into the current module, it will just have 0 constructor methods.
using AlgebraicAgents
@aagent MyAgent{T<:AbstractString} begin
myname::T
end
typeof(MyAgent)
methods(MyAgent)
dump(MyAgent)
It might be nice to allow users to define agents as parameterized types for when we still want each agent itself to have a fully concrete type to avoid type instability but also allow flexibility in the particular types, either for dispatch or to integrate with other packages (or for when large numbers of agents are being created programmatically). I will spend some time to think about how to do this, I'm still new to Julia metaprogramming.
It would be beneficial to incorporate the feature of loading and saving agent hierarchies from and to files in our package. Ideally, an agent hierarchy could be exported into a nested JSON structure. In this structure, specific attributes would be utilized to define the behavioral patterns of the agents.
In alignment with our general approach to package design, we should allow users to customize these load/save methods for their custom agent types.
Currently the indexing operator forwards to getobservable
. I've noticed in practical modeling however, we haven't used getobservable
very often (and when we do, it's not too much of an annoyance to type out getobservable(agent, keys)
). However, in projects, we often have code like inners(depot)["inventory"]
, or similar lines, appearing throughout the codebase repeatedly. What do you think of changing Base.getindex
to instead forward to inners(agent)[keys...]
?
Now that the call to _step!
is implemented as
# `step!` function
if (p = _projected_to(a); !isa(p, Bool) && (p == t))
_step!(a, t)
end
we could drop the second positional argument (t
) to _step!
.
Initially, _step!
(relative to agent
) was expected to perform the evolutionary step if and only if _projected_to(agent) == t
. We now check this condition in advance. Moreover, agent
may retrieve t
using _projected_to
.
Similar tutorials appear in three different places:
/tutorials
folderWe may remove /tutorials
folder after all, and some of the tutorial tests can be done implicitly when documentation is built.
Due to JuliaLang/julia#50538 and
AlgebraicAgents.jl/src/agents.jl
Lines 21 to 27 in e2a5935
it is not possible to precompile a module that makes a call to @aagent
.
Hi @thevolatilebit! My next plan is to write some tests/documentation for the Opera structure. I'm opening this issue and will close it when I've merged PR(s) that fulfill those goals.
I first had a few questions:
_interact!
?schedule_call
and schedule
?If we make a new agent type with @aagent
which has new additional data fields and construct it and print it to the REPL the Base.show
method will try to show it with undefined memory which doesn't cause a problem for the program (it keeps running) but results in an error message. We may want to keep this behavior to remind users that they need to manually need to initialize memory because of the way the macros work. I'm just flagging it as potentially worthy of a quick discussion.
MWE:
julia> using AlgebraicAgents
julia> @aagent MyAgent begin
myname::String
end
julia> MyAgent("Alice")
agent Alice with uuid 7d15f2a3 of type MyAgent
custom properties:Error showing value of type MyAgent:
ERROR: UndefRefError: access to undefined reference
Stacktrace:
@JuliaRegistrator register()
Hi @thevolatilebit, just curious how ports_in
should be used; there appears to be no tests for it. It seems it should link to an exposed port (observable) of another agent.
In a branch here, I was trying to figure it out: https://github.com/slwu89/AlgebraicAgents.jl/blob/c849f0032fe85888c910a3ec87ee0e1627ce0e42/test/integrations/sciml_test.jl#L126 Obviously that test will fail because the DiffEqAgent
constructor will call the dynamics function, and there is not yet anything in the ports_in
, but I am not sure what is the correct usage to be able to do something like in the test. Also in that branch I had to add a ports_in
method for Val{DummyType}
otherwise the constructor throws a method error.
This issue is used to trigger TagBot; feel free to unsubscribe.
If you haven't already, you should update your TagBot.yml
to include issue comment triggers.
Please see this post on Discourse for instructions and more details.
If you'd like for me to do this for you, comment TagBot fix
on this issue.
I'll open a PR within a few hours, please be patient!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.