Augmenting Model Workflows

We can apply our model augmentation framework to models that are compositions of component models.

We are going to use the model augmentation presented in examples/agentgraft.jl as a baseline simulation and build a workflow to compose that model with the example in examples/polynomial_regression.jl. It is strongly recommended that you understand those examples before following this notebook.

This example combines an agent based model of SIR diseases with a statistical model of polynomial regression to quantify the response of the agent based model with respect to one of its parameters. The input models have to be composed carefully in order to make the software work.

As taught by the scientific computing education group Software Carpentry, the best practice for composing scientific models is to have each component write files to disk and then use a workflow tool such as Make to orchestrate the execution of the modeling scripts.

An alternative approach is to design modeling frameworks for representing the models. The problem with this avenue becomes apparent when models are composed. The frameworks must be interoperable in order to make combined models. ModelTools avoids this problem by representing the models as code and manipulating the codes. The interoperation of two models is defined by user supplied functions in a fully featured programming language.

Let $m_1,m_2$ be models, and $t_1,t_2$ be tranformations and define $M_i = t_i(m_i)$. If we denote the creation of pipelines with the function composition symbol $g\circ f$ then we want to implement everything such that the following diagram commutes.

A diagram showing how pipelining commutes with tranforming models

This example shows how you can use a pipeline to represent the combination of models and then apply combinations of transformations to that pipeline. Transforming models and composing them into pipelines are two operations that commute, you can transform then compose or compose and then transform.

In [1]:
using SemanticModels.Parsers
using SemanticModels.ModelTools
using SemanticModels.ModelTools.ExpStateModels
import Base: push!
import SemanticModels.ModelTools: model, isexpr
using Random
In [2]:
samples = 100
nsteps = 25
finalcounts = Any[]
Out[2]:
0-element Array{Any,1}
In [3]:
println("Running Agent Based Simulation Augmentation Demo")
println("================================================")
println("demo parameters:\n\tsamples=$samples\n\tnsteps=$nsteps")
Running Agent Based Simulation Augmentation Demo
================================================
demo parameters:
	samples=100
	nsteps=25

Baseline SIRS model

Here is the baseline model, which is read in from a text file. You could instead of using parsefile use a quote/end block to code up the baseline model in this script.

In [4]:
expr = parsefile("../examples/agentbased.jl")
m = model(ExpStateModel, expr)
Out[4]:
ExpStateModel(
  states=:([:S, :I, :R]),
  agents=Expr[:(a = sm.agents), :(a = fill(:S, n))],
  transitions=Expr[:(T = Dict(:S => (x...->begin
                      #= none:120 =#
                      if rand(Float64) < stateload(x[1], :I)
                          :I
                      else
                          :S
                      end
                  end), :I => (x...->begin
                      #= none:121 =#
                      if rand(Float64) < ρ
                          :I
                      else
                          :R
                      end
                  end), :R => (x...->begin
                      #= none:122 =#
                      if rand(Float64) < μ
                          :R
                      else
                          :S
                      end
                  end)))]
)
In [5]:
function returns(block::Vector{Any})
    filter(x->(head(x)==:return), block)
end
returntuples = (bodyblock(filter(x->isa(x, Expr), findfunc(m.expr, :main))[end]) 
    |> returns 
    .|> x-> x.args[1].args )
push!(returntuples[1], :((ρ=ρ, μ=μ, n=n)))
Out[5]:
3-element Array{Any,1}:
 :newsam                 
 :counts                 
 :((ρ = ρ, μ = μ, n = n))
In [6]:
magents = m
println("\nRunning basic model")
AgentModels = eval(m.expr)
@show AgentModels
for i in 1:samples
    println(("======= . Simulation $i  ========"))
    newsam, counts, params = AgentModels.main(nsteps)
    push!(finalcounts, (model=:basic, counts=counts, params=params))
end
Running basic model
AgentModels = Main.AgentModels
======= . Simulation 1  ========
newsam.agents = Symbol[:R, :S, :R, :S, :I, :I, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S, :I, :S, :I]
======= . Simulation 2  ========
newsam.agents = Symbol[:I, :R, :R, :I, :S, :R, :I, :S, :I, :I, :I, :I, :I, :I, :I, :S, :I, :R, :R, :I]
======= . Simulation 3  ========
newsam.agents = Symbol[:R, :I, :S, :S, :S, :S, :R, :S, :S, :R, :R, :S, :R, :S, :S, :S, :S, :R, :S, :S]
======= . Simulation 4  ========
newsam.agents = Symbol[:S, :S, :S, :R, :S, :S, :R, :I, :R, :I, :R, :I, :S, :R, :I, :S, :S, :S, :R, :S]
======= . Simulation 5  ========
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 6  ========
newsam.agents = Symbol[:I, :S, :I, :R, :R, :I, :I, :I, :I, :I, :R, :R, :S, :R, :I, :S, :S, :I, :R, :I]
======= . Simulation 7  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
======= . Simulation 8  ========
newsam.agents = Symbol[:S, :S, :S, :I, :R, :S, :I, :S, :S, :S, :S, :R, :S, :S, :I, :S, :S, :S, :S, :R]
======= . Simulation 9  ========
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 10  ========
newsam.agents = Symbol[:S, :I, :S, :I, :S, :I, :S, :S, :I, :S, :I, :I, :I, :S, :S, :S, :I, :R, :S, :S]
======= . Simulation 11  ========
newsam.agents = Symbol[:R, :R, :R, :R, :R, :R, :R, :I, :I, :S, :I, :I, :S, :S, :I, :S, :I, :I, :S, :I]
======= . Simulation 12  ========
newsam.agents = Symbol[:S, :S, :R, :I, :R, :I, :R, :I, :S, :I, :I, :I, :R, :R, :S, :I, :S, :S, :S, :R]
======= . Simulation 13  ========
newsam.agents = Symbol[:I, :I, :S, :S, :I, :I, :I, :S, :S, :R, :S, :I, :R, :I, :I, :I, :I, :I, :R, :R]
======= . Simulation 14  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S]
======= . Simulation 15  ========
newsam.agents = Symbol[:R, :S, :I, :R, :S, :I, :I, :S, :I, :I, :S, :I, :I, :S, :I, :R, :S, :R, :R, :I]
======= . Simulation 16  ========
newsam.agents = Symbol[:I, :S, :S, :R, :I, :R, :R, :R, :R, :R, :R, :S, :S, :S, :S, :S, :I, :R, :S, :I]
======= . Simulation 17  ========
newsam.agents = Symbol[:S, :S, :R, :I, :S, :I, :S, :I, :I, :S, :I, :S, :I, :S, :R, :R, :I, :S, :R, :I]
======= . Simulation 18  ========
newsam.agents = Symbol[:S, :S, :R, :R, :S, :R, :S, :S, :R, :S, :I, :S, :R, :S, :I, :S, :S, :S, :S, :S]
======= . Simulation 19  ========
newsam.agents = Symbol[:S, :R, :I, :I, :R, :I, :R, :I, :R, :I, :I, :I, :I, :S, :I, :R, :I, :I, :R, :S]
======= . Simulation 20  ========
newsam.agents = Symbol[:S, :R, :S, :S, :R, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S, :R, :R, :S, :I, :R]
======= . Simulation 21  ========
newsam.agents = Symbol[:R, :S, :I, :I, :R, :I, :I, :I, :I, :I, :I, :I, :I, :S, :I, :I, :I, :I, :R, :S]
======= . Simulation 22  ========
newsam.agents = Symbol[:I, :I, :R, :R, :S, :R, :I, :R, :I, :S, :I, :S, :I, :R, :S, :I, :I, :S, :R, :I]
======= . Simulation 23  ========
newsam.agents = Symbol[:S, :S, :S, :I, :I, :S, :S, :I, :R, :I, :S, :I, :S, :S, :S, :S, :S, :R, :S, :S]
======= . Simulation 24  ========
newsam.agents = Symbol[:S, :I, :S, :S, :S, :S, :I, :I, :I, :I, :I, :I, :I, :R, :S, :S, :I, :I, :R, :S]
======= . Simulation 25  ========
newsam.agents = Symbol[:S, :I, :S, :I, :I, :R, :S, :I, :S, :S, :S, :I, :R, :R, :S, :R, :I, :R, :R, :I]
======= . Simulation 26  ========
newsam.agents = Symbol[:I, :R, :I, :S, :S, :I, :S, :R, :I, :R, :R, :R, :S, :I, :R, :S, :S, :S, :I, :I]
======= . Simulation 27  ========
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 28  ========
newsam.agents = Symbol[:S, :R, :R, :S, :S, :R, :R, :S, :I, :R, :I, :S, :R, :S, :S, :S, :S, :S, :I, :R]
======= . Simulation 29  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :I, :S, :I, :S, :R, :R, :S, :S, :R, :S, :S, :S, :S]
======= . Simulation 30  ========
newsam.agents = Symbol[:S, :R, :R, :I, :I, :S, :R, :S, :S, :R, :S, :S, :R, :R, :S, :R, :S, :R, :S, :S]
======= . Simulation 31  ========
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 32  ========
newsam.agents = Symbol[:R, :I, :S, :S, :S, :R, :S, :I, :S, :I, :S, :S, :I, :S, :I, :S, :I, :S, :R, :S]
======= . Simulation 33  ========
newsam.agents = Symbol[:S, :S, :R, :R, :S, :S, :S, :S, :R, :I, :S, :R, :S, :R, :R, :I, :I, :S, :R, :R]
======= . Simulation 34  ========
newsam.agents = Symbol[:S, :S, :I, :R, :I, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S]
======= . Simulation 35  ========
newsam.agents = Symbol[:S, :R, :S, :S, :R, :R, :R, :R, :I, :I, :S, :S, :R, :I, :S, :S, :I, :R, :I, :S]
======= . Simulation 36  ========
newsam.agents = Symbol[:S, :R, :R, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :R, :S, :I, :S, :R, :S]
======= . Simulation 37  ========
newsam.agents = Symbol[:S, :R, :I, :I, :S, :S, :S, :I, :R, :R, :S, :R, :R, :S, :S, :S, :S, :S, :R, :S]
======= . Simulation 38  ========
newsam.agents = Symbol[:I, :I, :R, :I, :R, :R, :I, :I, :I, :S, :I, :I, :S, :R, :I, :I, :R, :I, :I, :S]
======= . Simulation 39  ========
newsam.agents = Symbol[:I, :S, :S, :S, :R, :S, :S, :R, :I, :I, :I, :S, :S, :I, :I, :I, :R, :I, :S, :S]
======= . Simulation 40  ========
newsam.agents = Symbol[:S, :R, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S]
======= . Simulation 41  ========
newsam.agents = Symbol[:S, :I, :S, :R, :R, :S, :S, :I, :S, :R, :R, :I, :S, :R, :S, :S, :I, :I, :S, :I]
======= . Simulation 42  ========
newsam.agents = Symbol[:R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S]
======= . Simulation 43  ========
newsam.agents = Symbol[:S, :R, :S, :R, :R, :I, :S, :S, :S, :R, :S, :R, :S, :S, :R, :S, :S, :S, :S, :I]
======= . Simulation 44  ========
newsam.agents = Symbol[:R, :R, :S, :S, :I, :R, :S, :I, :S, :S, :I, :S, :S, :S, :S, :S, :S, :R, :S, :S]
======= . Simulation 45  ========
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 46  ========
newsam.agents = Symbol[:R, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :R]
======= . Simulation 47  ========
newsam.agents = Symbol[:R, :R, :R, :R, :R, :R, :S, :I, :S, :S, :R, :I, :R, :S, :I, :S, :R, :S, :R, :S]
======= . Simulation 48  ========
newsam.agents = Symbol[:R, :S, :I, :R, :I, :I, :I, :R, :I, :S, :I, :I, :R, :I, :I, :I, :I, :I, :R, :S]
======= . Simulation 49  ========
newsam.agents = Symbol[:R, :R, :I, :S, :S, :R, :S, :S, :R, :S, :S, :R, :S, :R, :S, :I, :R, :R, :R, :S]
======= . Simulation 50  ========
newsam.agents = Symbol[:I, :I, :I, :I, :I, :S, :S, :S, :S, :I, :S, :I, :I, :S, :I, :I, :I, :I, :R, :R]
======= . Simulation 51  ========
newsam.agents = Symbol[:S, :S, :S, :S, :R, :R, :S, :S, :S, :R, :R, :S, :S, :S, :I, :S, :S, :S, :S, :S]
======= . Simulation 52  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :R, :S, :I, :S, :S, :S, :S, :S, :S, :S]
======= . Simulation 53  ========
newsam.agents = Symbol[:S, :R, :R, :S, :I, :S, :I, :S, :R, :I, :S, :R, :S, :S, :I, :S, :I, :S, :S, :S]
======= . Simulation 54  ========
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 55  ========
newsam.agents = Symbol[:S, :S, :S, :I, :I, :S, :R, :S, :S, :I, :I, :R, :I, :S, :R, :I, :S, :R, :S, :S]
======= . Simulation 56  ========
newsam.agents = Symbol[:I, :R, :S, :R, :I, :I, :R, :I, :I, :I, :I, :I, :I, :I, :S, :I, :I, :I, :I, :I]
======= . Simulation 57  ========
newsam.agents = Symbol[:I, :R, :R, :I, :I, :R, :R, :S, :R, :S, :R, :I, :I, :I, :S, :R, :R, :R, :I, :S]
======= . Simulation 58  ========
newsam.agents = Symbol[:I, :I, :I, :S, :I, :I, :I, :I, :I, :I, :I, :R, :S, :I, :R, :S, :I, :I, :I, :S]
======= . Simulation 59  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :I, :S, :S, :R]
======= . Simulation 60  ========
newsam.agents = Symbol[:S, :I, :S, :S, :S, :R, :R, :S, :R, :S, :S, :S, :I, :R, :S, :S, :S, :I, :R, :S]
======= . Simulation 61  ========
newsam.agents = Symbol[:S, :S, :R, :R, :R, :I, :S, :R, :R, :R, :S, :S, :S, :S, :R, :S, :S, :S, :S, :R]
======= . Simulation 62  ========
newsam.agents = Symbol[:I, :I, :R, :R, :I, :S, :I, :I, :S, :I, :S, :S, :S, :R, :S, :I, :R, :R, :I, :I]
======= . Simulation 63  ========
newsam.agents = Symbol[:S, :S, :S, :S, :I, :R, :S, :S, :S, :R, :S, :R, :R, :R, :R, :S, :S, :S, :S, :S]
======= . Simulation 64  ========
newsam.agents = Symbol[:R, :R, :S, :S, :S, :R, :R, :R, :S, :R, :R, :I, :I, :I, :S, :I, :I, :I, :S, :I]
======= . Simulation 65  ========
newsam.agents = Symbol[:S, :S, :R, :R, :I, :I, :I, :R, :S, :I, :S, :I, :R, :R, :I, :S, :R, :R, :S, :S]
======= . Simulation 66  ========
newsam.agents = Symbol[:I, :I, :R, :I, :I, :I, :I, :R, :I, :R, :I, :I, :I, :I, :I, :S, :I, :S, :R, :R]
======= . Simulation 67  ========
newsam.agents = Symbol[:R, :R, :R, :S, :S, :S, :S, :R, :S, :S, :S, :S, :I, :S, :R, :I, :I, :S, :S, :R]
======= . Simulation 68  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
======= . Simulation 69  ========
newsam.agents = Symbol[:R, :I, :R, :S, :I, :S, :R, :S, :S, :S, :S, :S, :S, :R, :R, :I, :S, :S, :I, :I]
======= . Simulation 70  ========
newsam.agents = Symbol[:S, :S, :R, :R, :S, :R, :R, :S, :S, :R, :R, :S, :R, :S, :R, :S, :S, :S, :R, :S]
======= . Simulation 71  ========
newsam.agents = Symbol[:I, :I, :R, :I, :R, :S, :I, :R, :I, :S, :I, :I, :R, :I, :I, :S, :I, :R, :I, :I]
======= . Simulation 72  ========
newsam.agents = Symbol[:I, :I, :S, :I, :I, :I, :I, :I, :I, :I, :S, :I, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 73  ========
newsam.agents = Symbol[:S, :I, :I, :I, :I, :I, :I, :I, :S, :I, :I, :R, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 74  ========
newsam.agents = Symbol[:I, :S, :R, :I, :R, :R, :I, :I, :I, :I, :S, :I, :R, :S, :I, :S, :R, :I, :S, :I]
======= . Simulation 75  ========
newsam.agents = Symbol[:I, :R, :R, :S, :I, :I, :S, :S, :I, :S, :I, :S, :R, :S, :S, :R, :S, :S, :S, :S]
======= . Simulation 76  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :R, :S, :S, :S, :S, :S]
======= . Simulation 77  ========
newsam.agents = Symbol[:R, :S, :R, :I, :S, :S, :I, :R, :S, :I, :I, :I, :I, :S, :I, :S, :S, :I, :S, :I]
======= . Simulation 78  ========
newsam.agents = Symbol[:I, :I, :R, :R, :S, :S, :R, :R, :I, :S, :I, :I, :S, :S, :I, :S, :R, :S, :S, :S]
======= . Simulation 79  ========
newsam.agents = Symbol[:S, :R, :I, :R, :R, :I, :S, :R, :S, :I, :S, :S, :S, :I, :S, :R, :S, :R, :S, :S]
======= . Simulation 80  ========
newsam.agents = Symbol[:S, :R, :R, :I, :R, :R, :S, :S, :S, :S, :S, :R, :S, :S, :I, :I, :S, :S, :R, :R]
======= . Simulation 81  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
======= . Simulation 82  ========
newsam.agents = Symbol[:R, :S, :S, :R, :S, :R, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :R, :S]
======= . Simulation 83  ========
newsam.agents = Symbol[:I, :I, :R, :I, :I, :I, :I, :R, :S, :R, :I, :I, :S, :R, :I, :I, :R, :I, :I, :S]
======= . Simulation 84  ========
newsam.agents = Symbol[:S, :S, :I, :I, :I, :I, :I, :R, :S, :S, :I, :S, :R, :S, :S, :I, :I, :S, :R, :I]
======= . Simulation 85  ========
newsam.agents = Symbol[:R, :I, :S, :S, :R, :S, :I, :S, :S, :I, :R, :I, :S, :S, :S, :I, :I, :R, :I, :S]
======= . Simulation 86  ========
newsam.agents = Symbol[:S, :S, :I, :S, :I, :S, :I, :S, :I, :S, :S, :I, :S, :S, :S, :S, :I, :S, :I, :I]
======= . Simulation 87  ========
newsam.agents = Symbol[:S, :I, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I]
======= . Simulation 88  ========
newsam.agents = Symbol[:S, :S, :S, :S, :I, :R, :S, :R, :I, :S, :R, :I, :I, :S, :S, :R, :S, :R, :R, :S]
======= . Simulation 89  ========
newsam.agents = Symbol[:S, :I, :I, :I, :S, :S, :I, :I, :I, :R, :S, :R, :R, :R, :S, :R, :S, :R, :R, :S]
======= . Simulation 90  ========
newsam.agents = Symbol[:I, :S, :S, :S, :R, :I, :S, :I, :I, :R, :R, :I, :S, :R, :I, :S, :S, :I, :I, :S]
======= . Simulation 91  ========
newsam.agents = Symbol[:S, :S, :R, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
======= . Simulation 92  ========
newsam.agents = Symbol[:S, :I, :R, :R, :I, :S, :S, :R, :S, :I, :S, :S, :S, :S, :I, :S, :I, :I, :I, :R]
======= . Simulation 93  ========
newsam.agents = Symbol[:S, :I, :S, :I, :R, :R, :S, :R, :I, :S, :R, :I, :S, :S, :S, :R, :I, :S, :R, :R]
======= . Simulation 94  ========
newsam.agents = Symbol[:S, :I, :S, :I, :S, :S, :S, :S, :R, :R, :S, :R, :I, :S, :S, :I, :I, :R, :S, :S]
======= . Simulation 95  ========
newsam.agents = Symbol[:S, :S, :I, :R, :S, :R, :S, :R, :S, :S, :S, :S, :S, :R, :S, :R, :I, :S, :S, :I]
======= . Simulation 96  ========
newsam.agents = Symbol[:S, :I, :R, :I, :S, :I, :I, :I, :R, :S, :I, :I, :R, :R, :S, :R, :I, :R, :I, :S]
======= . Simulation 97  ========
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :I, :I, :R, :I, :R, :I, :S, :I, :R, :I, :S, :S]
======= . Simulation 98  ========
newsam.agents = Symbol[:R, :R, :S, :S, :R, :S, :I, :I, :I, :R, :S, :S, :S, :S, :R, :I, :S, :S, :S, :S]
======= . Simulation 99  ========
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
======= . Simulation 100  ========
newsam.agents = Symbol[:S, :R, :S, :R, :S, :R, :S, :S, :S, :S, :R, :S, :S, :S, :R, :S, :I, :S, :I, :S]
In [7]:
@show length(finalcounts)
finalcounts
length(finalcounts) = 100
Out[7]:
100-element Array{Any,1}:
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>13, :I=>5, :R=>2], params = (ρ = 0.36595158849792797, μ = 0.5, n = 20))
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>3, :I=>12, :R=>5], params = (ρ = 0.8303468433311483, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>13, :I=>1, :R=>6], params = (ρ = 0.538646017081199, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>10, :I=>4, :R=>6], params = (ρ = 0.132167513254612, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>0, :I=>20, :R=>0], params = (ρ = 0.9897354376550678, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>4, :I=>10, :R=>6], params = (ρ = 0.8107559433599498, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>19, :I=>0, :R=>1], params = (ρ = 0.4823819630195595, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>14, :I=>3, :R=>3], params = (ρ = 0.6459718393892384, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>0, :I=>20, :R=>0], params = (ρ = 1.152968173119568, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>11, :I=>8, :R=>1], params = (ρ = 0.42443831069608245, μ = 0.5, n = 20))
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>5, :I=>8, :R=>7], params = (ρ = 0.6416394830336656, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>7, :I=>7, :R=>6], params = (ρ = 0.8192164390474224, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>5, :I=>11, :R=>4], params = (ρ = 0.39984088571036186, μ = 0.5, n = 20))
 ⋮                                                                                                                       
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>7, :I=>6, :R=>7], params = (ρ = 0.4354373058021765, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>8, :I=>8, :R=>4], params = (ρ = 0.5770900576587538, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>18, :I=>0, :R=>2], params = (ρ = 0.3714578022156848, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>9, :I=>7, :R=>4], params = (ρ = 0.1683188004102073, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>8, :I=>5, :R=>7], params = (ρ = 0.4196388070851483, μ = 0.5, n = 20))  
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>11, :I=>5, :R=>4], params = (ρ = 0.37168858635990976, μ = 0.5, n = 20))
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>12, :I=>3, :R=>5], params = (ρ = 0.3335340652324803, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>5, :I=>9, :R=>6], params = (ρ = 0.46438215193377935, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>11, :I=>6, :R=>3], params = (ρ = 0.6140030608224631, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>11, :I=>4, :R=>5], params = (ρ = 0.3747158547696715, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>0, :I=>20, :R=>0], params = (ρ = 1.0031690942848939, μ = 0.5, n = 20)) 
 (model = :basic, counts = Pair{Symbol,Int64}[:S=>13, :I=>2, :R=>5], params = (ρ = 0.40806209026598544, μ = 0.5, n = 20))
In [8]:
ModelTools.invoke(magents, 10)[2:end]
newsam.agents = Symbol[:S, :S, :I, :S, :I, :I, :S, :S, :S, :R, :S, :I, :S, :S, :S, :S, :S, :S, :S, :I]
Out[8]:
(Pair{Symbol,Int64}[:S=>14, :I=>5, :R=>1], (ρ = 0.39531736748057666, μ = 0.5, n = 20))

Statistical Regression Model

The following expression defines a univariate polynomial regression model of degree 0, which just computes the average of target variable. This model can be augmented to an polynomial regression model using transformations $T_1,T_x$ which will be defined later.

In [9]:
expr = quote
    module Regression
    using Random
    using LsqFit
    using LinearAlgebra

    function f(x, β)
        # This .+ node is added so that we have something to grab onto
        # in the metaprogramming. It is the ∀a .+(a) == a. 
        return .+(β[1].* x.^0)
    end

    function sample(g::Function, n)
        x = randn(Float64, n)
        target = g(x) .+ randn(Float64, n[1])./1600
        return x, target
    end

    function describe(fit)
        if !fit.converged
            error("Did not converge")
        end
        return (β = fit.param, r=norm(fit.resid,2), n=length(fit.resid))
    end
    #setup
    a₀ = [1.0]
    function main(X, target)
        #solving
        fit = curve_fit(f, X, target, a₀)#; autodiff=:forwarddiff)
        result = describe(fit)
        return fit, result
    end
end
end
Regression = eval(expr.args[2])
┌ Info: Recompiling stale cache file /Users/jfairbanks6/.julia/compiled/v1.0/LsqFit/GCdY9.ji for LsqFit [2fda8390-95c7-5789-9bda-21331edee243]
└ @ Base loading.jl:1190
Out[9]:
Main.Regression
In [10]:
function connector(finalcounts)
    n = length(finalcounts)
    Data = zeros(n,length(finalcounts[1].counts))
    @show size(Data)
    for i in 1:n
        c = finalcounts[i].counts
        Data[i, : ] = map(last, c)
    end
    # multivariate regression not yet supported
    # X = Data[:, 1:end-2]
    # Y = Data[:, end]
    # @assert(size(X) == (n,size(Data,2)-2))
    # @assert(size(Y) == (n,))
    X = Data[:, 1]
    Y = Data[:, 2]
    @assert size(X,1) == size(Y,1)
    return X,Y
end
Out[10]:
connector (generic function with 1 method)
In [11]:
X,Y = connector(finalcounts)
collect(zip(X,Y))
size(Data) = (100, 3)
Out[11]:
100-element Array{Tuple{Float64,Float64},1}:
 (13.0, 5.0)
 (3.0, 12.0)
 (13.0, 1.0)
 (10.0, 4.0)
 (0.0, 20.0)
 (4.0, 10.0)
 (19.0, 0.0)
 (14.0, 3.0)
 (0.0, 20.0)
 (11.0, 8.0)
 (5.0, 8.0) 
 (7.0, 7.0) 
 (5.0, 11.0)
 ⋮          
 (7.0, 6.0) 
 (8.0, 8.0) 
 (18.0, 0.0)
 (9.0, 7.0) 
 (8.0, 5.0) 
 (11.0, 5.0)
 (12.0, 3.0)
 (5.0, 9.0) 
 (11.0, 6.0)
 (11.0, 4.0)
 (0.0, 20.0)
 (13.0, 2.0)
In [12]:
fit, result = Regression.main(connector(finalcounts)...)
result
size(Data) = (100, 3)
Out[12]:
(β = [6.67], r = 55.19157544408385, n = 100)
In [13]:
if sum(fit.resid)/length(fit.resid) > 1e-8
    @warn "Mean residual is large, regression might have failed"
end

Implementation Details

The following code is the implementation details for representing the models as an AbstractProblem and representing the transformations as Product{Tuple{Pow{Int}, Pow{Int}}} and applying the transformations onto the models.

See the examples/polynomial_regression.jl example for details of what this code does.

In [14]:
using LinearAlgebra
using SemanticModels
using SemanticModels.ModelTools
using SemanticModels.ModelTools.Transformations
import SemanticModels.ModelTools: model, AbstractModel, isexpr
import SemanticModels.Parsers: findfunc, findassign
import Base: show
In [15]:
"""    Lsq


A program that solves min_β || f(X,β) - y ||_2

Example:

`f(X, β) = β[1].*X.^p .+ β[2].*X.^q`

See also [`(t::Pow)(m::MultivariateLsq)`](@ref)
"""
struct Lsq <: AbstractModel
    expr
    f
    coefficient
    p₀
end

function show(io::IO, m::Lsq)
    write(io, "Lsq(\n  f=$(repr(m.f)),\n  coefficient=$(repr(m.coefficient)),\n  p₀=$(repr(m.p₀))\n)")
end

function model(::Type{Lsq}, expr::Expr)
    if expr.head == :block
        return model(Lsq, expr.args[2])
    end
    objective = :l2norm
    f = callsites(expr, :curve_fit)[end].args[2]
    coeff = callsites(expr, f)[1].args[end]
    p₀ = callsites(expr, :curve_fit)[end].args[end]
    return Lsq(expr, f, coeff, p₀)
end

"""    poly(m::Lsq)::Expr

find the part of the model that implements the polynomial model for regression.
"""
function poly(m::Lsq)
    func = findfunc(m.expr, m.f)[1]
    poly = func.args[2].args[end].args[1]
    return poly
end

"""    (t::Pow)(m::Lsq)

Example:

If `m` is a program implementing `f(X, β) = β[1]*X^p + β[2]*X^q`

a) and `t = Pow(2)` then `t(m)` is the model implementing
`f(X, β) = β[1]*X^p+2 + β[2]*X^q+q`.

"""
function (t::Pow)(m::Lsq)
    p = poly(m)
    for i in 2:length(p.args)
        slot = p.args[i]
        pow = callsites(slot, :(.^))
        pow[end].args[3] += t.inc
    end
    return m
end
Out[15]:
SemanticModels.ModelTools.Transformations.Pow
In [16]:
struct AddConst <: Transformations.Transformation end

"""    (c::AddConst)(m::MultivariateLsq)

Example:

If `m` is a program implementing `f(X, β) = β[1]*X^p + β[2]*X^q`

a) and `c = AddConst()` then `c(m)` is the model implementing
`f(X, β) = β[1]*X^p + β[2]*X^0`.

"""
function (c::AddConst)(m::Lsq)
    p = poly(m)
    ix = map(t->t.args[2].args[2], p.args[2:end])
    i = maximum(ix)+1
    @show p
    push!(p.args, :(β[$i].*x.^0))
    assigns = findassign(m.expr, m.p₀)
    @show assigns
    b = assigns[end].args[2].args
    push!(b, 1)
    return m
end
Out[16]:
AddConst

Model Augmentation yields polynomial regression

Given our transformations f(x) -> xf(x) and f(x) -> f(x) + beta we are able to generate all possible polynomial regression using composition of these transformations.

In [17]:
# Let's build an instance of the model object from the code snippet expr
m = model(Lsq, deepcopy(expr))
mstats = deepcopy(m)
@show m
poly(m)
m = Lsq(
  f=:f,
  coefficient=:β,
  p₀=:a₀
)
Out[17]:
:((.+)(β[1] .* x .^ 0))

Some generator elements will come in handy for building elements of the transformation group. $T_x,T_1$ are generators for our group of transformations $T = \langle T_x, T_1 \rangle$. $T_1$ adds a constant to our polynomial and $T_x$ increments all the powers of the terms by 1. Any polynomial can be generated by these two operations. The proof of Horner's rule for evaluating $p(x)$ gives a construction for how to create $f(x,\beta) = p(x)$ from these two operations.

In [18]:
@show Tₓ = Pow(1)
@show T₁ = AddConst()
Tₓ, T₁
Tₓ = Pow(1) = Pow(1)
T₁ = AddConst() = AddConst()
Out[18]:
(Pow(1), AddConst())
In [19]:
m′ = deepcopy(m)
Tₓ(m′)
T₁(m′)
@show poly(m)
Regression = eval(m′.expr)
p = :((.+)(β[1] .* x .^ 1))
assigns = Expr[:(a₀ = [1.0])]
poly(m) = :((.+)(β[1] .* x .^ 0))
WARNING: replacing module Regression.
Out[19]:
Main.Regression
In [20]:
@show m′.expr
fit′, result′ = Regression.main(connector(finalcounts)...)
result′
m′.expr = :(module Regression
  #= In[9]:3 =#
  #= In[9]:4 =#
  using Random
  #= In[9]:5 =#
  using LsqFit
  #= In[9]:6 =#
  using LinearAlgebra
  #= In[9]:8 =#
  function f(x, β)
      #= In[9]:11 =#
      return β[1] .* x .^ 1 .+ β[2] .* x .^ 0
  end
  #= In[9]:14 =#
  function sample(g::Function, n)
      #= In[9]:15 =#
      x = randn(Float64, n)
      #= In[9]:16 =#
      target = g(x) .+ randn(Float64, n[1]) ./ 1600
      #= In[9]:17 =#
      return (x, target)
  end
  #= In[9]:20 =#
  function describe(fit)
      #= In[9]:21 =#
      if !(fit.converged)
          #= In[9]:22 =#
          error("Did not converge")
      end
      #= In[9]:24 =#
      return (β = fit.param, r = norm(fit.resid, 2), n = length(fit.resid))
  end
  #= In[9]:27 =#
  a₀ = [1.0, 1]
  #= In[9]:28 =#
  function main(X, target)
      #= In[9]:30 =#
      fit = curve_fit(f, X, target, a₀)
      #= In[9]:31 =#
      result = describe(fit)
      #= In[9]:32 =#
      return (fit, result)
  end
  end)
size(Data) = (100, 3)
Out[20]:
(β = [-0.95976, 15.471], r = 24.55902326382762, n = 100)
In [21]:
result′.r
Out[21]:
24.55902326382762

Model workflows

Models can be chained together into workflows, the most basic type is a pipeline where the outputs from model $m_i$ are passed to model $m_{i+1}$. One area where traditional modeling frameworks get in trouble is the fact that the connections between the models can be arbitrarily complex. Thus any modeling framework that supports worflows, must embed a programming language for describing the connectors between the steps of the workflow.

Since we are already embedded in Julia, we will use regular Julia functions for the connectors.

Mathematically, a pipeline is defined as $r_n = P(m_1,\dots,m_n, c_1,\dots,c_n)$ based on the recurrence,

$r_0 = m_1(c)$ where $c$ is a constant value, and

$r_i = m_i(c_i(r_{i-1}))$

We store the values of $r_i$ in the field results so that they can be accessed later by visualization and analysis programs.

In [22]:
module Pipelines
using SemanticModels.ModelTools
using Random
struct Pipeline <: AbstractModel
    steps
    connectors
    results
end

function run!(p::Pipeline)
    stages = length(p.steps)
    connectors = p.connectors
    for s in 1:stages
        data = p.results[end]
        r = connectors[s](p.steps[s], data...)
        push!(p.results, r)
    end
end

function reset!(p::Pipeline)
    while length(p.results) > 1
        pop!(p.results)
    end
    return p
end
end
Out[22]:
Main.Pipelines

Running the baseline workflow

This workflow connects the two models so that we simulate the agent based model and then perform a regression on the outputs.

In [23]:
P = Pipelines.Pipeline(deepcopy.([magents, mstats]),
    [(m, args...) -> begin 
            Random.seed!(42)
            results = Any[]
            Mod = eval(m.expr)
            for i in 1:samples
                r = Base.invokelatest(Mod.main, args...)
                push!(results, (model=:basic, counts=r[2], params=r[3]))
                #push!(results, r)
            end
            return [results]
                end,
        (m, results...) -> begin
            data = connector(results...)
            Mod = eval(m.expr)
            Base.invokelatest(Mod.main, data...) end
        ],
        Any[(10)]
        )
Out[23]:
Main.Pipelines.Pipeline(AbstractModel[ExpStateModel(
  states=:([:S, :I, :R]),
  agents=Expr[:(a = sm.agents), :(a = fill(:S, n))],
  transitions=Expr[:(T = Dict(:S => (x...->begin
                      #= none:120 =#
                      if rand(Float64) < stateload(x[1], :I)
                          :I
                      else
                          :S
                      end
                  end), :I => (x...->begin
                      #= none:121 =#
                      if rand(Float64) < ρ
                          :I
                      else
                          :R
                      end
                  end), :R => (x...->begin
                      #= none:122 =#
                      if rand(Float64) < μ
                          :R
                      else
                          :S
                      end
                  end)))]
), Lsq(
  f=:f,
  coefficient=:β,
  p₀=:a₀
)], Function[##11#13(), ##12#14()], Any[10])

Warning: Pipelines can only be run once. Recreate the pipeline and run it again if necessary.

In [24]:
Pipelines.run!(P)
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :R, :S, :S, :I]
newsam.agents = Symbol[:R, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :S, :S, :I, :I, :R, :I, :I, :I, :S, :R, :S, :R, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:I, :S, :R, :S, :S, :S, :R, :S, :S, :S, :S, :S, :R, :R, :R, :R, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :S, :R, :R, :S, :S, :S, :R, :I, :S, :S, :S, :I, :S, :R, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:R, :R, :R, :S, :S, :I, :S, :I, :R, :I, :S, :S, :S, :S, :S, :S, :S, :S, :R, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :R, :I, :I, :S, :R, :I, :I, :R, :I, :R, :I, :I, :I, :R, :I, :I]
newsam.agents = Symbol[:S, :R, :S, :S, :R, :S, :R, :S, :S, :S, :R, :S, :R, :S, :S, :R, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :S, :S, :I, :I, :R, :S, :R, :R, :S, :S, :R, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :I, :S, :R, :S, :R, :S, :S, :R, :S, :S, :S, :R, :S, :S, :R, :S, :S, :S]
newsam.agents = Symbol[:R, :R, :I, :S, :I, :S, :R, :I, :R, :I, :I, :I, :S, :I, :I, :I, :R, :S, :I, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :R, :I, :I, :I, :I, :I, :I, :I, :R, :R, :I, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S, :S, :I, :R, :S, :I, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :S, :R, :I, :R, :R, :R, :I, :S, :S, :S, :R, :R, :S, :R, :R, :I, :I, :S]
newsam.agents = Symbol[:S, :R, :I, :I, :I, :R, :R, :S, :R, :S, :S, :S, :R, :S, :I, :S, :I, :R, :R, :I]
newsam.agents = Symbol[:S, :I, :S, :S, :I, :S, :S, :S, :I, :S, :I, :R, :S, :S, :S, :S, :S, :S, :I, :I]
newsam.agents = Symbol[:S, :S, :R, :S, :R, :S, :I, :R, :R, :I, :I, :R, :R, :R, :S, :S, :I, :S, :I, :S]
newsam.agents = Symbol[:I, :S, :R, :I, :R, :S, :S, :S, :S, :S, :R, :I, :I, :S, :R, :R, :R, :R, :I, :I]
newsam.agents = Symbol[:I, :R, :S, :I, :S, :I, :S, :S, :S, :S, :I, :R, :R, :I, :S, :I, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :R, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :R, :I, :S, :R, :I, :S, :S, :I, :R, :I, :R, :S, :S, :I, :S, :I, :R, :R, :S]
newsam.agents = Symbol[:I, :S, :R, :R, :I, :S, :I, :S, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:R, :R, :S, :S, :I, :S, :S, :S, :S, :S, :R, :S, :R, :S, :S, :I, :S, :S, :R, :S]
newsam.agents = Symbol[:R, :S, :S, :S, :S, :S, :S, :R, :S, :S, :R, :S, :R, :I, :I, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :I, :I, :R, :R, :R, :R, :R, :I, :I, :R, :S, :R, :R, :S, :I, :R, :S, :S, :S]
newsam.agents = Symbol[:R, :S, :S, :S, :I, :S, :R, :S, :S, :S, :S, :I, :S, :R, :R, :I, :R, :R, :S, :S]
newsam.agents = Symbol[:S, :S, :I, :I, :R, :I, :I, :I, :R, :S, :I, :I, :S, :I, :I, :S, :I, :I, :S, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :R, :R, :I, :I, :S, :S, :R, :I, :R, :S]
newsam.agents = Symbol[:I, :R, :S, :S, :S, :R, :I, :I, :S, :I, :S, :I, :R, :S, :I, :R, :I, :I, :I, :I]
newsam.agents = Symbol[:I, :I, :S, :I, :I, :I, :I, :I, :S, :I, :S, :I, :I, :R, :R, :I, :I, :S, :I, :I]
newsam.agents = Symbol[:S, :S, :I, :S, :S, :I, :R, :S, :S, :I, :R, :I, :R, :S, :R, :R, :R, :S, :R, :R]
newsam.agents = Symbol[:S, :I, :R, :S, :S, :I, :I, :R, :R, :S, :S, :S, :R, :S, :I, :I, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :S, :R, :I, :S, :I, :S, :I, :I, :I, :S, :I, :I, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :R, :I, :I, :R, :I, :I, :R, :S, :I, :I, :S, :I, :I, :I, :R]
newsam.agents = Symbol[:I, :R, :S, :I, :S, :I, :I, :S, :I, :I, :I, :I, :I, :S, :S, :S, :I, :S, :I, :R]
newsam.agents = Symbol[:I, :S, :I, :S, :R, :I, :I, :S, :R, :I, :S, :I, :S, :S, :I, :I, :I, :I, :I, :R]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:S, :S, :R, :S, :S, :S, :S, :S, :R, :S, :R, :I, :I, :I, :R, :S, :R, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :S, :R, :R, :I, :R, :I, :R, :I, :I, :I, :R, :I, :I]
newsam.agents = Symbol[:S, :I, :S, :R, :S, :S, :S, :S, :S, :S, :I, :R, :S, :S, :S, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:I, :S, :R, :S, :S, :S, :I, :S, :S, :I, :R, :S, :S, :S, :S, :R, :S, :S, :I, :R]
newsam.agents = Symbol[:S, :S, :R, :R, :R, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :R, :S, :I, :I, :S, :R, :I]
newsam.agents = Symbol[:S, :S, :I, :S, :S, :I, :S, :R, :R, :I, :S, :I, :S, :I, :R, :S, :R, :I, :R, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:R, :S, :I, :S, :R, :S, :S, :S, :R, :S, :R, :S, :I, :R, :S, :S, :R, :R, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :R, :I, :R, :R, :R, :R, :R, :S, :R, :S, :S, :R, :I, :S, :I, :I]
newsam.agents = Symbol[:S, :I, :S, :S, :S, :I, :S, :S, :S, :S, :R, :S, :I, :S, :S, :S, :R, :S, :S, :S]
newsam.agents = Symbol[:S, :R, :S, :S, :R, :S, :R, :S, :I, :R, :I, :R, :R, :S, :I, :I, :S, :S, :I, :R]
newsam.agents = Symbol[:S, :R, :I, :R, :S, :S, :S, :R, :R, :R, :S, :S, :R, :R, :S, :S, :R, :S, :S, :I]
newsam.agents = Symbol[:S, :I, :I, :I, :I, :S, :R, :R, :I, :R, :R, :I, :I, :I, :I, :S, :S, :I, :R, :R]
newsam.agents = Symbol[:S, :R, :I, :S, :R, :S, :I, :R, :S, :S, :I, :I, :R, :S, :R, :S, :S, :R, :S, :I]
newsam.agents = Symbol[:R, :R, :R, :I, :S, :R, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :R, :I, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :I, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S, :S, :I, :R]
newsam.agents = Symbol[:I, :S, :I, :R, :S, :I, :I, :I, :R, :I, :I, :R, :I, :S, :R, :I, :S, :I, :R, :I]
newsam.agents = Symbol[:S, :S, :R, :S, :S, :R, :I, :I, :I, :I, :R, :S, :I, :S, :I, :I, :I, :R, :I, :R]
newsam.agents = Symbol[:S, :S, :I, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S, :S, :I, :R, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :S, :S, :S, :S, :R, :I, :R, :I, :S, :S, :S, :S, :I, :S, :I, :I, :R, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :I, :S, :R, :S, :S, :S, :I, :R, :S, :S, :S, :S, :R, :R]
newsam.agents = Symbol[:S, :I, :I, :S, :I, :R, :I, :R, :I, :I, :I, :R, :I, :S, :R, :I, :R, :I, :S, :I]
newsam.agents = Symbol[:I, :I, :S, :I, :S, :S, :R, :R, :S, :R, :S, :S, :S, :S, :I, :S, :R, :R, :R, :S]
newsam.agents = Symbol[:I, :I, :I, :R, :I, :I, :R, :R, :R, :R, :I, :I, :I, :S, :I, :S, :S, :R, :I, :I]
newsam.agents = Symbol[:R, :S, :S, :R, :S, :S, :S, :S, :S, :I, :R, :S, :S, :S, :S, :S, :R, :S, :R, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :I]
newsam.agents = Symbol[:I, :R, :I, :I, :S, :I, :R, :I, :R, :I, :S, :I, :I, :R, :R, :R, :I, :R, :I, :S]
newsam.agents = Symbol[:S, :R, :R, :R, :S, :R, :S, :S, :S, :I, :I, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :S, :I, :I, :I, :I, :R, :I, :R, :I, :I, :I, :I, :R, :I, :I, :I, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :R, :I, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :R, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :R, :I, :R, :S, :I, :S, :S, :R, :R, :S, :I, :S, :S, :S, :S, :S, :S, :R, :I]
newsam.agents = Symbol[:S, :R, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S]
newsam.agents = Symbol[:R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :R, :I, :I, :S, :I, :R, :I, :I, :I, :S, :S, :S, :S, :I, :I, :I]
newsam.agents = Symbol[:R, :R, :S, :R, :S, :R, :I, :R, :S, :I, :S, :R, :S, :S, :S, :S, :R, :S, :S, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :R, :I, :R, :S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :R, :I, :R, :I, :I, :R, :R, :S, :S, :I, :S, :S, :R, :S, :R, :S, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :I, :S, :S, :R, :S, :S, :S, :S, :S, :I, :I, :S, :S, :I, :S, :S]
newsam.agents = Symbol[:S, :S, :R, :R, :I, :R, :R, :R, :I, :S, :R, :R, :S, :I, :S, :R, :I, :S, :I, :I]
newsam.agents = Symbol[:S, :S, :R, :I, :S, :I, :I, :R, :I, :R, :R, :S, :S, :I, :I, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :R, :S, :S, :S, :I, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :R, :I, :I, :I, :I, :R, :I, :I, :I, :I, :I, :I, :I, :I, :R]
newsam.agents = Symbol[:S, :S, :S, :R, :R, :S, :S, :S, :S, :S, :R, :I, :R, :I, :I, :I, :I, :I, :S, :R]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :I, :S, :R, :R, :R, :S, :S, :S, :S, :S, :R, :I, :S, :S, :I, :I, :S, :R, :I]
newsam.agents = Symbol[:R, :I, :I, :R, :S, :R, :S, :I, :I, :S, :R, :R, :I, :S, :I, :S, :I, :I, :I, :R]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :I, :I, :R, :R, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:R, :I, :S, :I, :I, :I, :I, :R, :S, :I, :R, :I, :I, :S, :I, :S, :I, :R, :I, :I]
newsam.agents = Symbol[:I, :R, :S, :I, :I, :I, :R, :I, :I, :R, :I, :R, :R, :I, :I, :S, :R, :I, :I, :S]
newsam.agents = Symbol[:R, :S, :S, :I, :S, :I, :I, :I, :S, :S, :I, :S, :I, :I, :S, :S, :S, :I, :R, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :R, :S, :R, :R, :S, :S, :S, :S, :S, :S, :S, :R, :S, :R, :S]
newsam.agents = Symbol[:R, :I, :S, :I, :S, :I, :S, :S, :S, :S, :I, :S, :S, :I, :S, :S, :I, :I, :S, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :I, :R, :S, :R, :R, :S, :S, :R, :S, :I, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :R, :S, :R, :S, :S, :S, :S, :R, :S, :R, :S, :R, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :I, :S, :R, :R, :S, :R, :S, :R, :S, :R, :S, :S, :R, :R, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :R, :R, :S, :R, :S, :S, :R, :R, :S, :S, :R, :I, :S, :I, :I, :I, :R, :I]
newsam.agents = Symbol[:S, :S, :R, :I, :I, :S, :S, :S, :S, :S, :I, :S, :S, :I, :S, :S, :S, :R, :S, :S]
size(Data) = (100, 3)
WARNING: replacing module AgentModels.
WARNING: replacing module Regression.
In [25]:
for r in P.results[end]
    println(r)
    println("==========")
end
LsqFit.LsqFitResult{Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,1}}([6.56], [4.56, 5.56, -6.44, 4.56, 4.56, 2.56, -7.44, 6.56, 0.56, 5.56, -3.44, -10.44, 3.56, 0.56, 0.56, 0.56, 1.56, 0.56, -0.44, 6.56, -0.44, -8.44, 4.56, 4.56, 6.56, 1.56, 3.56, -5.44, 3.56, -3.44, -7.44, 2.56, 1.56, -8.44, -7.44, -4.44, -4.44, 6.56, 3.56, -7.44, 4.56, 2.56, 6.56, -8.44, 0.56, -13.44, 4.56, -1.44, 3.56, 1.56, 4.56, -3.44, 1.56, 4.56, 3.56, -4.44, -2.44, 3.56, 0.56, 4.56, -4.44, 2.56, -4.44, 5.56, 4.56, -3.44, 4.56, -9.44, -13.44, -12.44, 4.56, 2.56, 5.56, 6.56, -6.44, 3.56, -13.44, 5.56, 0.56, 2.56, 0.56, 0.56, 5.56, -10.44, 0.56, 4.56, 1.56, -2.44, 4.56, -5.44, -4.44, -2.44, 6.56, -1.44, 4.56, 6.56, -13.44, 5.56, 0.56, 2.56], [1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0], true, Float64[])
==========
(β = [6.56], r = 54.851071092550235, n = 100)
==========
In [26]:
Tₓ(P.steps[2])
T₁(P.steps[2])
Tₓ(P.steps[2])
T₁(P.steps[2])
p = :((.+)(β[1] .* x .^ 1))
assigns = Expr[:(a₀ = [1.0])]
p = :(β[1] .* x .^ 2 .+ β[2] .* x .^ 1)
assigns = Expr[:(a₀ = [1.0, 1])]
Out[26]:
Lsq(
  f=:f,
  coefficient=:β,
  p₀=:a₀
)
In [27]:
Pipelines.reset!(P)
Pipelines.run!(P)
P.results[end][2]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :R, :S, :S, :I]
newsam.agents = Symbol[:R, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :S, :S, :I, :I, :R, :I, :I, :I, :S, :R, :S, :R, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:I, :S, :R, :S, :S, :S, :R, :S, :S, :S, :S, :S, :R, :R, :R, :R, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :S, :R, :R, :S, :S, :S, :R, :I, :S, :S, :S, :I, :S, :R, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:R, :R, :R, :S, :S, :I, :S, :I, :R, :I, :S, :S, :S, :S, :S, :S, :S, :S, :R, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :R, :I, :I, :S, :R, :I, :I, :R, :I, :R, :I, :I, :I, :R, :I, :I]
newsam.agents = Symbol[:S, :R, :S, :S, :R, :S, :R, :S, :S, :S, :R, :S, :R, :S, :S, :R, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :S, :S, :I, :I, :R, :S, :R, :R, :S, :S, :R, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :I, :S, :R, :S, :R, :S, :S, :R, :S, :S, :S, :R, :S, :S, :R, :S, :S, :S]
newsam.agents = Symbol[:R, :R, :I, :S, :I, :S, :R, :I, :R, :I, :I, :I, :S, :I, :I, :I, :R, :S, :I, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :R, :I, :I, :I, :I, :I, :I, :I, :R, :R, :I, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S, :S, :I, :R, :S, :I, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :S, :R, :I, :R, :R, :R, :I, :S, :S, :S, :R, :R, :S, :R, :R, :I, :I, :S]
newsam.agents = Symbol[:S, :R, :I, :I, :I, :R, :R, :S, :R, :S, :S, :S, :R, :S, :I, :S, :I, :R, :R, :I]
newsam.agents = Symbol[:S, :I, :S, :S, :I, :S, :S, :S, :I, :S, :I, :R, :S, :S, :S, :S, :S, :S, :I, :I]
newsam.agents = Symbol[:S, :S, :R, :S, :R, :S, :I, :R, :R, :I, :I, :R, :R, :R, :S, :S, :I, :S, :I, :S]
newsam.agents = Symbol[:I, :S, :R, :I, :R, :S, :S, :S, :S, :S, :R, :I, :I, :S, :R, :R, :R, :R, :I, :I]
newsam.agents = Symbol[:I, :R, :S, :I, :S, :I, :S, :S, :S, :S, :I, :R, :R, :I, :S, :I, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :R, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :R, :I, :S, :R, :I, :S, :S, :I, :R, :I, :R, :S, :S, :I, :S, :I, :R, :R, :S]
newsam.agents = Symbol[:I, :S, :R, :R, :I, :S, :I, :S, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:R, :R, :S, :S, :I, :S, :S, :S, :S, :S, :R, :S, :R, :S, :S, :I, :S, :S, :R, :S]
newsam.agents = Symbol[:R, :S, :S, :S, :S, :S, :S, :R, :S, :S, :R, :S, :R, :I, :I, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :I, :I, :R, :R, :R, :R, :R, :I, :I, :R, :S, :R, :R, :S, :I, :R, :S, :S, :S]
newsam.agents = Symbol[:R, :S, :S, :S, :I, :S, :R, :S, :S, :S, :S, :I, :S, :R, :R, :I, :R, :R, :S, :S]
newsam.agents = Symbol[:S, :S, :I, :I, :R, :I, :I, :I, :R, :S, :I, :I, :S, :I, :I, :S, :I, :I, :S, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :R, :R, :I, :I, :S, :S, :R, :I, :R, :S]
newsam.agents = Symbol[:I, :R, :S, :S, :S, :R, :I, :I, :S, :I, :S, :I, :R, :S, :I, :R, :I, :I, :I, :I]
newsam.agents = Symbol[:I, :I, :S, :I, :I, :I, :I, :I, :S, :I, :S, :I, :I, :R, :R, :I, :I, :S, :I, :I]
newsam.agents = Symbol[:S, :S, :I, :S, :S, :I, :R, :S, :S, :I, :R, :I, :R, :S, :R, :R, :R, :S, :R, :R]
newsam.agents = Symbol[:S, :I, :R, :S, :S, :I, :I, :R, :R, :S, :S, :S, :R, :S, :I, :I, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :S, :R, :I, :S, :I, :S, :I, :I, :I, :S, :I, :I, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :R, :I, :I, :R, :I, :I, :R, :S, :I, :I, :S, :I, :I, :I, :R]
newsam.agents = Symbol[:I, :R, :S, :I, :S, :I, :I, :S, :I, :I, :I, :I, :I, :S, :S, :S, :I, :S, :I, :R]
newsam.agents = Symbol[:I, :S, :I, :S, :R, :I, :I, :S, :R, :I, :S, :I, :S, :S, :I, :I, :I, :I, :I, :R]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:S, :S, :R, :S, :S, :S, :S, :S, :R, :S, :R, :I, :I, :I, :R, :S, :R, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :S, :R, :R, :I, :R, :I, :R, :I, :I, :I, :R, :I, :I]
newsam.agents = Symbol[:S, :I, :S, :R, :S, :S, :S, :S, :S, :S, :I, :R, :S, :S, :S, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:I, :S, :R, :S, :S, :S, :I, :S, :S, :I, :R, :S, :S, :S, :S, :R, :S, :S, :I, :R]
newsam.agents = Symbol[:S, :S, :R, :R, :R, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :R, :S, :I, :I, :S, :R, :I]
newsam.agents = Symbol[:S, :S, :I, :S, :S, :I, :S, :R, :R, :I, :S, :I, :S, :I, :R, :S, :R, :I, :R, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:R, :S, :I, :S, :R, :S, :S, :S, :R, :S, :R, :S, :I, :R, :S, :S, :R, :R, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :R, :I, :R, :R, :R, :R, :R, :S, :R, :S, :S, :R, :I, :S, :I, :I]
newsam.agents = Symbol[:S, :I, :S, :S, :S, :I, :S, :S, :S, :S, :R, :S, :I, :S, :S, :S, :R, :S, :S, :S]
newsam.agents = Symbol[:S, :R, :S, :S, :R, :S, :R, :S, :I, :R, :I, :R, :R, :S, :I, :I, :S, :S, :I, :R]
newsam.agents = Symbol[:S, :R, :I, :R, :S, :S, :S, :R, :R, :R, :S, :S, :R, :R, :S, :S, :R, :S, :S, :I]
newsam.agents = Symbol[:S, :I, :I, :I, :I, :S, :R, :R, :I, :R, :R, :I, :I, :I, :I, :S, :S, :I, :R, :R]
newsam.agents = Symbol[:S, :R, :I, :S, :R, :S, :I, :R, :S, :S, :I, :I, :R, :S, :R, :S, :S, :R, :S, :I]
newsam.agents = Symbol[:R, :R, :R, :I, :S, :R, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S, :R, :I, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :I, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S, :S, :I, :R]
newsam.agents = Symbol[:I, :S, :I, :R, :S, :I, :I, :I, :R, :I, :I, :R, :I, :S, :R, :I, :S, :I, :R, :I]
newsam.agents = Symbol[:S, :S, :R, :S, :S, :R, :I, :I, :I, :I, :R, :S, :I, :S, :I, :I, :I, :R, :I, :R]
newsam.agents = Symbol[:S, :S, :I, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S, :S, :I, :R, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :S, :S, :S, :S, :R, :I, :R, :I, :S, :S, :S, :S, :I, :S, :I, :I, :R, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :I, :S, :R, :S, :S, :S, :I, :R, :S, :S, :S, :S, :R, :R]
newsam.agents = Symbol[:S, :I, :I, :S, :I, :R, :I, :R, :I, :I, :I, :R, :I, :S, :R, :I, :R, :I, :S, :I]
newsam.agents = Symbol[:I, :I, :S, :I, :S, :S, :R, :R, :S, :R, :S, :S, :S, :S, :I, :S, :R, :R, :R, :S]
newsam.agents = Symbol[:I, :I, :I, :R, :I, :I, :R, :R, :R, :R, :I, :I, :I, :S, :I, :S, :S, :R, :I, :I]
newsam.agents = Symbol[:R, :S, :S, :R, :S, :S, :S, :S, :S, :I, :R, :S, :S, :S, :S, :S, :R, :S, :R, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :I]
newsam.agents = Symbol[:I, :R, :I, :I, :S, :I, :R, :I, :R, :I, :S, :I, :I, :R, :R, :R, :I, :R, :I, :S]
newsam.agents = Symbol[:S, :R, :R, :R, :S, :R, :S, :S, :S, :I, :I, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :S, :I, :I, :I, :I, :R, :I, :R, :I, :I, :I, :I, :R, :I, :I, :I, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :R, :I, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :R, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :R, :I, :R, :S, :I, :S, :S, :R, :R, :S, :I, :S, :S, :S, :S, :S, :S, :R, :I]
newsam.agents = Symbol[:S, :R, :S, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S]
newsam.agents = Symbol[:R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :R, :I, :I, :S, :I, :R, :I, :I, :I, :S, :S, :S, :S, :I, :I, :I]
newsam.agents = Symbol[:R, :R, :S, :R, :S, :R, :I, :R, :S, :I, :S, :R, :S, :S, :S, :S, :R, :S, :S, :I]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :R, :I, :R, :S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :R, :I, :R, :I, :I, :R, :R, :S, :S, :I, :S, :S, :R, :S, :R, :S, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :I, :S, :S, :R, :S, :S, :S, :S, :S, :I, :I, :S, :S, :I, :S, :S]
newsam.agents = Symbol[:S, :S, :R, :R, :I, :R, :R, :R, :I, :S, :R, :R, :S, :I, :S, :R, :I, :S, :I, :I]
newsam.agents = Symbol[:S, :S, :R, :I, :S, :I, :I, :R, :I, :R, :R, :S, :S, :I, :I, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :R, :S, :S, :S, :I, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :R, :I, :I, :I, :I, :R, :I, :I, :I, :I, :I, :I, :I, :I, :R]
newsam.agents = Symbol[:S, :S, :S, :R, :R, :S, :S, :S, :S, :S, :R, :I, :R, :I, :I, :I, :I, :I, :S, :R]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :I, :S, :R, :R, :R, :S, :S, :S, :S, :S, :R, :I, :S, :S, :I, :I, :S, :R, :I]
newsam.agents = Symbol[:R, :I, :I, :R, :S, :R, :S, :I, :I, :S, :R, :R, :I, :S, :I, :S, :I, :I, :I, :R]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :I, :I, :R, :R, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:R, :I, :S, :I, :I, :I, :I, :R, :S, :I, :R, :I, :I, :S, :I, :S, :I, :R, :I, :I]
newsam.agents = Symbol[:I, :R, :S, :I, :I, :I, :R, :I, :I, :R, :I, :R, :R, :I, :I, :S, :R, :I, :I, :S]
newsam.agents = Symbol[:R, :S, :S, :I, :S, :I, :I, :I, :S, :S, :I, :S, :I, :I, :S, :S, :S, :I, :R, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :R, :S, :R, :R, :S, :S, :S, :S, :S, :S, :S, :R, :S, :R, :S]
newsam.agents = Symbol[:R, :I, :S, :I, :S, :I, :S, :S, :S, :S, :I, :S, :S, :I, :S, :S, :I, :I, :S, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :I, :R, :S, :R, :R, :S, :S, :R, :S, :I, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :R, :S, :R, :S, :S, :S, :S, :R, :S, :R, :S, :R, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :I, :S, :R, :R, :S, :R, :S, :R, :S, :R, :S, :S, :R, :R, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :R, :R, :S, :R, :S, :S, :R, :R, :S, :S, :R, :I, :S, :I, :I, :I, :R, :I]
newsam.agents = Symbol[:S, :S, :R, :I, :I, :S, :S, :S, :S, :S, :I, :S, :S, :I, :S, :S, :S, :R, :S, :S]
size(Data) = (100, 3)
WARNING: replacing module AgentModels.
WARNING: replacing module Regression.
Out[27]:
(β = [0.0512554, -1.8639, 18.1003], r = 17.29034597600283, n = 100)
  1. TODO implement the composition monoid on ExpStateModels
  2. TODO use Product acting on Pipeline to represent Tuple.coordinates == Pipeline.steps
In [28]:
# Product = ModelTools.Transformations.Product
function (t::Product)(m::Pipelines.Pipeline)
    for (i, s) in enumerate(m.steps)
        t.dims[i](s)
    end
end

Adding the Dead State

We are going to add an additional state to the model to represent the infectious disease fatalities. The user must specify what that concept means in terms of the name for the new state and the behavior of that state. D is a terminal state for a finite automata.

In [29]:
function addstate!(m::ExpStateModel)
    println("\nThe system states are $(m.states.args)")
    println("\nAdding un estado de los muertos")

    put!(m, ExpStateTransition(:D, :((x...)->:D)))

    println("\nThe system states are $(m.states.args)")
    # once you are dead, you are dead forever
    println("\nThere is no resurrection in this model")
    println("\nInfected individuals recover or die in one step")

    # replace!(m, ExpStateTransition(:I, :((x...)->rand(Bool) ? :D : :I)))
    m[:I] = :((x...)->begin
            roll = rand()
            if roll < ρ
                return :R
            elseif rand(Bool)
                return :D
            else
                return :I
            end
        end
    )
    @show m[:I]
    return m
end
Out[29]:
addstate! (generic function with 1 method)

Some utilities for manipulating functions at a higher level than expressions.

In [30]:
struct Func end

function push!(::Func, func::Expr, ex::Expr)
    push!(bodyblock(func), ex)
end
Out[30]:
push! (generic function with 65 methods)

Population Growth

Another change we can make to our model is the introduction of population growth. Our model for population is that on each timestep, one new suceptible person will be added to the list of agents. We use the tick! function as an anchor point for this transformation.

In [31]:
function addgrowth!(m::ExpStateModel)
    println("\nAdding population growth to this model")
    stepr = filter(x->isa(x,Expr), findfunc(m.expr, :tick!))[1]
    @show stepr
    push!(Func(), stepr, :(push!(sm.agents, :S)))
    println("------------------------")
    @show stepr;
    return m
end
Out[31]:
addgrowth! (generic function with 1 method)

Transforming the Pipeline

We can apply the tranformations that we defined onto the pipeline. Remember that $T_1\times T_2$ acts on a pipeline by creating $P(T_1(m_1),T_2(m_2), c_1,c_2)$. The current implementation does not support transforming the connectors, but that would be straightforward to add.

In [32]:
function connector(finalcounts, i, j)
    n = length(finalcounts)
    Data = zeros(n,length(finalcounts[1].counts))
    params = zeros(n,length(finalcounts[1].params))
    @show size(Data)
    for i in 1:n
        c = finalcounts[i].counts
        Data[i, : ] = map(last, c)
        params[i,:] = collect(map(float, finalcounts[i].params))
    end
    # multivariate regression not yet supported
    # X = Data[:, 1:end-2]
    # Y = Data[:, end]
    # @assert(size(X) == (n,size(Data,2)-2))
    # @assert(size(Y) == (n,))
    X = params[:, i]
    Y = Data[:, j]
    # normalization
    #Y = Y ./ [sum(Data[i, :]) for i in 1:n]
    @assert size(X,1) == size(Y,1)
    return X,Y
end
P = Pipelines.Pipeline(deepcopy.([magents, mstats]),
    [(m, args...) -> begin 
            Random.seed!(42)
            results = Any[]
            Mod = eval(m.expr)
            @show Mod
            for i in 1:samples
                r = Base.invokelatest(Mod.main, args...)
                push!(results, (model=:basic, counts=r[2],params=r[3]))
                #push!(results, r)
            end
            return [results]
                end,
        (m, results...) -> begin
            data = connector(results..., 1, 4)
            Mod = eval(m.expr)
            Base.invokelatest(Mod.main, data...) 
        end
        ],
        Any[(10)]
        )
println("\nInitial Pipeline")
println("----------------")
@show P.steps[1].states
@show poly(P.steps[2])
println("\n\nApplying the first pair of transformations")
println(     "------------------------------------------")
Product((addstate!, one(Pow)))(P)
@show P.steps[1].states
@show poly(P.steps[2])
println("\n\nApplying the second pair of transformations")
println(    "-------------------------------------------")
Product((x->x, AddConst()))(P)
Product((addgrowth!, one(Pow)))(P)
Product((x->x, AddConst()))(P)
Product((x->x, one(Pow)))(P)
Product((x->x, AddConst()))(P)
println("\n\nThe final model state")
println(     "---------------------")
println(filter(isexpr, findfunc(P.steps[1].expr, :tick!))[end])
@show poly(P.steps[2]);
Initial Pipeline
----------------
(P.steps[1]).states = :([:S, :I, :R])
poly(P.steps[2]) = :((.+)(β[1] .* x .^ 0))


Applying the first pair of transformations
------------------------------------------

The system states are Any[:(:S), :(:I), :(:R)]

Adding un estado de los muertos

The system states are Any[:(:S), :(:I), :(:R), :(:D)]

There is no resurrection in this model

Infected individuals recover or die in one step
m[:I] = :(x...->begin
          #= In[29]:13 =#
          #= In[29]:14 =#
          roll = rand()
          #= In[29]:15 =#
          if roll < ρ
              #= In[29]:16 =#
              return :R
          elseif #= In[29]:17 =# rand(Bool)
              #= In[29]:18 =#
              return :D
          else
              #= In[29]:20 =#
              return :I
          end
      end)
(P.steps[1]).states = :([:S, :I, :R, :D])
poly(P.steps[2]) = :((.+)(β[1] .* x .^ 1))


Applying the second pair of transformations
-------------------------------------------
p = :((.+)(β[1] .* x .^ 1))
assigns = Expr[:(a₀ = [1.0])]

Adding population growth to this model
stepr = :(function tick!(sm::StateModel)
      #= none:59 =#
      sm.loads = map((s->begin
                      #= none:59 =#
                      stateload(sm, s)
                  end), sm.states)
      #= none:60 =#
      return sm.loads
  end)
------------------------
stepr = :(function tick!(sm::StateModel)
      #= none:59 =#
      sm.loads = map((s->begin
                      #= none:59 =#
                      stateload(sm, s)
                  end), sm.states)
      #= none:60 =#
      return sm.loads
      push!(sm.agents, :S)
  end)
p = :(β[1] .* x .^ 2 .+ β[2] .* x .^ 1)
assigns = Expr[:(a₀ = [1.0, 1])]
p = :(.+(β[1] .* x .^ 3, β[2] .* x .^ 2, β[3] .* x .^ 1))
assigns = Expr[:(a₀ = [1.0, 1, 1])]


The final model state
---------------------
function tick!(sm::StateModel)
    #= none:59 =#
    sm.loads = map((s->begin
                    #= none:59 =#
                    stateload(sm, s)
                end), sm.states)
    #= none:60 =#
    return sm.loads
    push!(sm.agents, :S)
end
poly(P.steps[2]) = :(.+(β[1] .* x .^ 3, β[2] .* x .^ 2, β[3] .* x .^ 1, β[4] .* x .^ 0))

Running the new pipeline

now that we have transformed the pipeline we run it to build the results

In [33]:
Pipelines.run!(P)
P.results[end][2]
Mod = Main.AgentModels
newsam.agents = 
WARNING: replacing module AgentModels.
Symbol[:S, :D, :D, :S, :D, :S, :S, :S, :S, :S, :D, :S, :D, :D, :D, :S, :D, :S, :S, :D]
newsam.agents = Symbol[:S, :S, :R, :S, :S, :S, :S, :R, :S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :R, :S, :S, :D, :D, :R, :R, :D, :I, :D, :S, :R, :R, :R, :D, :S, :R, :D]
newsam.agents = Symbol[:S, :S, :I, :S, :S, :S, :S, :S, :D, :S, :S, :S, :I, :S, :S, :S, :S, :S, :D, :S]
newsam.agents = Symbol[:D, :D, :D, :R, :D, :D, :D, :S, :D, :D, :S, :D, :D, :D, :D, :D, :D, :D, :D, :D]
newsam.agents = Symbol[:D, :S, :D, :S, :D, :S, :S, :S, :D, :S, :S, :S, :D, :D, :S, :S, :D, :D, :D, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :R, :S, :R, :S, :R, :R, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:D, :D, :S, :S, :D, :D, :S, :S, :D, :D, :D, :D, :D, :S, :D, :S, :S, :S, :D, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S, :D, :S, :S, :D, :S, :S, :D, :D, :I]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :D, :D, :S]
newsam.agents = Symbol[:D, :D, :D, :D, :I, :R, :D, :D, :D, :D, :D, :D, :D, :I, :R, :S, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :R, :R, :S, :D, :S, :S, :S, :D, :S, :R, :S, :D, :S, :R, :S, :I, :S, :R, :R]
newsam.agents = Symbol[:S, :S, :S, :I, :S, :R, :S, :S, :I, :S, :R, :S, :S, :R, :S, :S, :S, :D, :D, :S]
newsam.agents = Symbol[:R, :D, :S, :R, :D, :S, :D, :S, :S, :I, :R, :D, :R, :S, :S, :S, :D, :S, :S, :D]
newsam.agents = Symbol[:I, :S, :D, :R, :I, :R, :S, :S, :S, :S, :S, :D, :D, :S, :D, :S, :S, :I, :D, :D]
newsam.agents = Symbol[:D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :I, :D, :D, :D, :D, :D, :D, :D, :D, :D]
newsam.agents = Symbol[:R, :S, :S, :R, :I, :D, :R, :S, :R, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:D, :R, :D, :R, :S, :S, :S, :D, :S, :S, :S, :S, :S, :S, :S, :S, :I, :D, :S, :S]
newsam.agents = Symbol[:D, :R, :D, :D, :D, :S, :R, :S, :S, :S, :D, :I, :D, :R, :S, :I, :D, :D, :R, :D]
newsam.agents = Symbol[:S, :D, :S, :D, :D, :S, :S, :D, :D, :S, :S, :S, :S, :D, :S, :D, :D, :S, :D, :D]
newsam.agents = Symbol[:D, :S, :I, :S, :S, :S, :S, :S, :D, :S, :D, :S, :D, :S, :S, :S, :R, :D, :D, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :R, :R, :S, :S, :S, :S, :S, :S, :R, :S, :S, :S, :R, :S, :S]
newsam.agents = Symbol[:S, :D, :D, :S, :S, :R, :I, :D, :S, :D, :D, :S, :S, :S, :D, :S, :R, :R, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :S, :S, :I, :S, :S, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :S, :S, :D, :D, :S, :S, :S, :D, :D, :D, :D, :S, :D, :S, :D, :S, :D, :S, :S]
newsam.agents = Symbol[:S, :S, :R, :S, :S, :I, :S, :S, :S, :S, :R, :I, :S, :S, :R, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:D, :D, :R, :R, :D, :S, :I, :R, :R, :S, :R, :I, :R, :R, :R, :R, :D, :D, :S, :D]
newsam.agents = Symbol[:S, :R, :S, :S, :D, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :I, :R, :S, :S, :D]
newsam.agents = Symbol[:S, :D, :R, :D, :D, :I, :D, :D, :D, :I, :D, :D, :S, :D, :D, :D, :I, :S, :D, :S]
newsam.agents = Symbol[:S, :S, :D, :I, :D, :S, :R, :D, :D, :I, :S, :R, :S, :I, :R, :S, :S, :R, :R, :I]
newsam.agents = Symbol[:S, :S, :I, :S, :I, :S, :S, :I, :S, :S, :R, :S, :I, :I, :R, :D, :S, :D, :S, :S]
newsam.agents = Symbol[:R, :S, :R, :D, :S, :D, :D, :R, :I, :R, :S, :D, :R, :I, :R, :D, :S, :R, :D, :I]
newsam.agents = Symbol[:D, :R, :S, :S, :S, :S, :D, :D, :D, :D, :D, :S, :D, :D, :D, :S, :S, :S, :D, :R]
newsam.agents = Symbol[:S, :S, :S, :D, :S, :R, :S, :D, :I, :D, :D, :S, :I, :R, :S, :D, :S, :D, :S, :S]
newsam.agents = Symbol[:S, :D, :D, :D, :D, :D, :S, :S, :S, :D, :R, :D, :D, :S, :D, :D, :S, :S, :D, :D]
newsam.agents = Symbol[:S, :R, :S, :I, :S, :R, :R, :D, :S, :D, :D, :D, :D, :S, :D, :I, :R, :S, :R, :I]
newsam.agents = Symbol[:I, :S, :S, :S, :S, :D, :S, :S, :R, :S, :S, :S, :S, :R, :S, :D, :S, :D, :S, :I]
newsam.agents = Symbol[:D, :S, :S, :D, :S, :I, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :D, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :D, :D, :D, :S, :D, :S, :S, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :S]
newsam.agents = Symbol[:S, :D, :D, :D, :D, :D, :D, :D, :D, :S, :D, :S, :I, :D, :D, :D, :D, :D, :I, :I]
newsam.agents = Symbol[:S, :S, :S, :R, :S, :S, :R, :S, :S, :S, :S, :D, :S, :R, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :I, :D, :D, :R, :R, :D, :I, :S, :S, :D, :D, :S, :I, :R, :D, :I, :D, :S]
newsam.agents = Symbol[:D, :S, :S, :S, :D, :S, :R, :D, :I, :D, :D, :S, :S, :S, :D, :D, :D, :D, :D, :S]
newsam.agents = Symbol[:R, :S, :S, :S, :I, :S, :D, :I, :I, :S, :R, :R, :D, :S, :S, :R, :R, :R, :D, :I]
newsam.agents = Symbol[:R, :S, :S, :R, :S, :S, :I, :D, :S, :R, :S, :S, :R, :S, :R, :R, :S, :S, :R, :D]
newsam.agents = Symbol[:S, :S, :S, :I, :S, :S, :S, :S, :S, :D, :S, :S, :S, :S, :D, :S, :I, :S, :S, :S]
newsam.agents = Symbol[:D, :S, :S, :D, :I, :D, :S, :D, :D, :D, :D, :S, :S, :D, :S, :S, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :D, :S, :S, :D, :S, :S, :S, :S, :R, :D, :D, :D, :D, :D, :S, :I, :S, :S, :S]
newsam.agents = Symbol[:S, :D, :S, :D, :S, :I, :D, :I, :S, :S, :S, :I, :S, :S, :R, :S, :D, :R, :S, :S]
newsam.agents = Symbol[:D, :R, :D, :S, :I, :D, :S, :D, :D, :S, :S, :S, :S, :S, :D, :I, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :R, :S, :S, :S, :S, :S, :S, :D, :S, :R, :S, :S, :I, :D, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :D, :D, :S, :S, :R, :S, :S, :S, :S, :S, :S, :D, :S, :D, :D, :D, :S]
newsam.agents = Symbol[:S, :D, :S, :S, :S, :I, :S, :D, :D, :D, :D, :D, :D, :S, :S, :S, :S, :D, :S, :I]
newsam.agents = Symbol[:S, :D, :R, :I, :R, :S, :I, :S, :I, :D, :S, :D, :S, :S, :I, :I, :S, :S, :S, :S]
newsam.agents = Symbol[:I, :S, :S, :D, :D, :D, :D, :D, :S, :D, :D, :S, :D, :S, :S, :S, :S, :D, :D, :D]
newsam.agents = Symbol[:S, :I, :S, :D, :S, :S, :S, :R, :D, :S, :S, :S, :I, :R, :I, :R, :S, :S, :D, :R]
newsam.agents = Symbol[:D, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :D, :S, :S]
newsam.agents = Symbol[:D, :R, :S, :S, :R, :R, :S, :R, :S, :D, :D, :R, :R, :S, :S, :D, :S, :S, :R, :D]
newsam.agents = Symbol[:S, :S, :S, :S, :D, :S, :D, :S, :S, :S, :S, :D, :D, :D, :D, :S, :S, :D, :S, :D]
newsam.agents = Symbol[:D, :S, :S, :R, :I, :S, :S, :I, :I, :S, :S, :S, :S, :S, :R, :R, :D, :I, :S, :I]
newsam.agents = Symbol[:D, :S, :S, :D, :S, :D, :S, :S, :D, :D, :S, :S, :S, :S, :D, :S, :D, :S, :S, :S]
newsam.agents = Symbol[:I, :D, :D, :D, :D, :D, :D, :S, :D, :R, :S, :D, :S, :S, :D, :S, :D, :D, :D, :D]
newsam.agents = Symbol[:D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D]
newsam.agents = Symbol[:S, :D, :R, :D, :S, :I, :S, :R, :D, :S, :S, :S, :S, :S, :D, :I, :S, :S, :D, :S]
newsam.agents = Symbol[:S, :S, :S, :D, :S, :S, :S, :S, :S, :S, :S, :S, :D, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :D, :D, :D, :D, :D, :D, :D, :S, :D, :R, :S, :D, :D, :S, :D, :S, :D, :D, :D]
newsam.agents = Symbol[:D, :S, :D, :D, :R, :D, :S, :D, :S, :I, :D, :D, :D, :S, :I, :I, :D, :D, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :S, :D, :D, :S, :S, :S, :S, :S, :S, :D, :S, :S, :D, :S, :S]
newsam.agents = Symbol[:D, :S, :S, :I, :S, :D, :S, :S, :D, :S, :S, :D, :S, :D, :S, :S, :I, :R, :D, :D]
newsam.agents = Symbol[:S, :S, :R, :S, :S, :S, :R, :S, :S, :S, :S, :S, :I, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :D, :D, :S, :S, :S, :D, :D, :I, :S, :D, :I, :D, :D, :D, :S]
newsam.agents = Symbol[:S, :D, :S, :D, :S, :D, :S, :R, :S, :D, :S, :S, :D, :S, :I, :S, :D, :R, :S, :D]
newsam.agents = Symbol[:D, :D, :S, :S, :R, :D, :D, :S, :S, :D, :D, :D, :D, :D, :D, :R, :D, :R, :D, :S]
newsam.agents = Symbol[:S, :S, :S, :D, :S, :I, :I, :D, :R, :R, :I, :R, :R, :S, :S, :R, :S, :S, :S, :I]
newsam.agents = Symbol[:S, :S, :S, :I, :S, :S, :D, :I, :I, :D, :D, :D, :S, :S, :D, :R, :D, :S, :D, :S]
newsam.agents = Symbol[:D, :S, :D, :D, :D, :S, :D, :D, :S, :D, :D, :D, :S, :D, :D, :S, :D, :D, :S, :D]
newsam.agents = Symbol[:S, :R, :S, :I, :S, :S, :D, :S, :S, :S, :D, :R, :S, :R, :S, :S, :D, :I, :R, :D]
newsam.agents = Symbol[:S, :S, :S, :I, :S, :S, :D, :S, :S, :R, :S, :D, :D, :R, :D, :S, :S, :I, :S, :S]
newsam.agents = Symbol[:R, :S, :S, :S, :R, :S, :R, :S, :I, :R, :S, :S, :S, :I, :I, :S, :S, :S, :D, :D]
newsam.agents = Symbol[:D, :D, :S, :S, :S, :D, :D, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :I, :D, :I]
newsam.agents = Symbol[:S, :D, :R, :R, :R, :D, :I, :D, :I, :S, :R, :D, :D, :R, :S, :D, :D, :D, :D, :D]
newsam.agents = Symbol[:D, :R, :D, :S, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :S, :S, :S, :S, :D, :D]
newsam.agents = Symbol[:D, :D, :D, :D, :D, :I, :I, :D, :I, :D, :I, :D, :I, :S, :I, :R, :D, :D, :S, :D]
newsam.agents = Symbol[:D, :D, :D, :D, :D, :D, :D, :D, :R, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D, :D]
newsam.agents = Symbol[:I, :I, :S, :S, :D, :D, :I, :D, :S, :D, :D, :I, :S, :S, :S, :S, :S, :S, :S, :R]
newsam.agents = Symbol[:I, :S, :D, :S, :S, :R, :S, :S, :S, :S, :R, :S, :D, :D, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :D, :S, :S, :S, :D, :D, :S, :R, :R, :R, :S, :D, :D, :D, :R, :S, :S]
newsam.agents = Symbol[:S, :D, :I, :D, :R, :S, :S, :D, :R, :R, :S, :S, :S, :S, :S, :S, :I, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :I, :S, :S, :S, :I, :S, :I, :S, :S, :S, :S, :S, :S, :I, :S]
newsam.agents = Symbol[:S, :S, :S, :D, :D, :I, :R, :D, :R, :S, :D, :S, :D, :S, :S, :D, :D, :D, :S, :D]
newsam.agents = Symbol[:S, :S, :D, :S, :D, :D, :S, :D, :S, :S, :S, :D, :S, :D, :S, :S, :D, :S, :S, :S]
newsam.agents = Symbol[:D, :S, :R, :D, :S, :D, :S, :S, :S, :S, :D, :S, :S, :S, :S, :S, :D, :S, :D, :R]
newsam.agents = Symbol[:R, :R, :S, :S, :R, :I, :S, :S, :S, :S, :R, :R, :R, :I, :S, :I, :S, :S, :D, :R]
newsam.agents = Symbol[:S, :R, :S, :R, :R, :S, :S, :S, :S, :S, :R, :S, :S, :S, :R, :S, :S, :I, :S, :S]
newsam.agents = Symbol[:S, :S, :R, :S, :S, :D, :S, :S, :S, :S, :R, :I, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:R, :S, :S, :R, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S, :S]
newsam.agents = Symbol[:S, :S, :S, :S, :S, :I, :S, :S, :S, :D, :D, :S, :S, :S, :S, :S, :R, :S, :I, :I]
newsam.agents = Symbol[:R, :R, :D, :S, :R, :I, :I, :S, :S, :S, :D, :D, :D, :S, :S, :S, :I, :I, :S, :D]
newsam.agents = Symbol[:S, :R, :D, :R, :S, :S, :D, :S, :S, :D, :S, :D, :D, :D, :S, :S, :D, :S, :R, :S]
newsam.agents = Symbol[:R, :S, :D, :I, :D, :D, :D, :D, :S, :D, :S, :D, :R, :D, :D, :D, :D, :R, :D, :D]
size(Data) = (100, 4)
WARNING: replacing module Regression.
Out[33]:
(β = [32.4032, -43.9778, -0.99626, 13.2007], r = 25.657138767118166, n = 100)

Here is the data we observed when running the first stage of the pipeline, stage two fits a polynomial to these observations

In [ ]:
table = map(x->(round(x.params.ρ, digits=4), last(x.counts[end])), P.results[2][1]) |> sort
try 
    using Plots
catch
    @warn "Plotting is not available, make a table"
    for t in table
        println(join(t, "\t"))
    end
end
┌ Info: Recompiling stale cache file /Users/jfairbanks6/.julia/compiled/v1.0/Plots/ld3vC.ji for Plots [91a5bcdd-55d7-5caf-9e0b-520d859cae80]
└ @ Base loading.jl:1190

Results

The regression model that we have trained based on the simulated data from the SIRD model with population growth can be presented as a polynomial sampled over the domain. We construct this table to show the nonlinear dependence of the model on the recovery parameter $\rho$. The best fitting polynomial is shown below.

In [ ]:
using Printf
eval(:(f(x,β) = $(poly(P.steps[2]))))
xdomain = (0.0:0.05:1.0)
println(\tf(ρ,β)\n==============")
xŷ = zip(xdomain, f(xdomain, P.results[end][2].β))
z = collect(map(x->(@sprintf("%0.2f", x[1]),
                    @sprintf("%7.3f", x[2])),
        xŷ))
for t in z
    println(join(t, "\t"))
end
In [ ]:
@info "Loading Plots, this may take a while"
using Plots
In [ ]:
@info "Making plots, this may take a while"
p = scatter(first.(table), last.(table), label="obs")
plot!(first.(xŷ), last.(xŷ), label="fit")
xlabel!(p, "Probability of Recovery")
ylabel!(p, "Deaths")
println("β: ", P.results[end][2].β, "\n", string(poly(P.steps[2])))
p

Conclusions

This example shows that the SemanticModels approach to post-hoc modeling frameworks can enable metamodeling which is the combinations of model composed using different technologies into a coherent modeling workflow. Our ModelTools provides the basic building blocks for representing models and transformations in such a way that they transformations can be composed and models can be combined. Composition of transformations respects the combination of models. In this case the Product of transformation respects the Pipeline of models. Such that you can transform the models and then pipeline them, or pipeline them and then transform them.

This example combined an agent based model of SIR diseases with a statistical model of polynomial regression to quantify the response of the agent based model with respect to one of its parameters. The input models have to be composed carefully in order to make the software work.

As taught by the scientific computing education group Software Carpentry, the best practice for composing scientific models is to have each component write files to disk and then use a workflow tool such as Make to orchestrate the execution of the modeling scripts.

An alternative approach is to design modeling frameworks for representing the models. The problem with this avenue becomes apparent when models are composed. The frameworks must be interoperable in order to make combined models. ModelTools avoids this problem by representing the models as code and manipulating the codes. The interoperation of two models is defined by user supplied functions in a fully featured programming language.

SemanticModels.jl also provides transformations on these models that are grounded in category theory and abstract algebra. The concepts of category theory such as Functors and Product Categories allow us to build a general framework fit for any modeling task. In the language of category theory, the Pipelining functor on models commutes with the Product functor on transformations.

This examples shows that metamodeling is feasible with SemanticModels and that the algebras of model transformations can be preserved when acting on metamodel workflows.