Skip to content

Commit

Permalink
No need to use NumericFuns because generic functions have been inline…
Browse files Browse the repository at this point in the history
…d in julia v0.5

See: JuliaLang/julia#13412

Can possibly improve this by storing V as an Expression instead of a String

NB: To create the sparse matrix, V must be a single expression containing an array, hence :([expr; expr; …]). Otherwise, the previous way, storing an array of expressions: [:(expr); :(expr); …] required that the variables endo, exo, and param be defined in the space where the function was going to be called, which was less than ideal. If I can figure out a way to pass the value to the function, then this would be ideal.

NB: Also that the solution outlined here: https://groups.google.com/forum/#!topic/julia-users/87_BMRY7Du4 does not work when ex is an array of expressions: [:(expr); :(expr); …]
  • Loading branch information
houtanb committed Sep 27, 2017
1 parent 783e9e1 commit b740765
Showing 1 changed file with 20 additions and 24 deletions.
44 changes: 20 additions & 24 deletions tests/julia_derivative_test/preprocessor.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import JSON
import SymEngine
using NumericFuns

# NB: SymEngine converts Basic("e") => E,
# but Basic("e(-1)") => symbols("e(-1)")
Expand All @@ -16,10 +15,6 @@ const nonDynareSymEngineKeyWordSymEngineSymbolSub = SymEngine.symbols(nonDynareS
const nonDynareSymEngineKeyWordAtom = DynareModel.Endo(nonDynareSymEngineKeyWordString, nonDynareSymEngineKeyWordString, nonDynareSymEngineKeyWordString)
# END NB

type StaticG1 <: Functor{3} end
type StaticG2 <: Functor{3} end
type DynamicG1 <: Functor{3} end

function process(modfile::String)
# Run Dynare preprocessor get JSON output
json = run_preprocessor(modfile)
Expand Down Expand Up @@ -69,10 +64,12 @@ function process(modfile::String)
model["end_val"]) = parse_json(json)

# Calculate derivatives
(staticg1ref, staticg2ref, dynamicg1ref) = compose_derivatives(model)
# (staticg1ref, staticg2ref, dynamicg1ref) = compose_derivatives(model)
(StaticG1, StaticG2, DynamicG1) = compose_derivatives(model)

# Return JSON and Julia representation of modfile
(json, model, StaticG1, staticg1ref, StaticG2, staticg2ref, DynamicG1, dynamicg1ref)
# (json, model, StaticG1, staticg1ref, StaticG2, staticg2ref, DynamicG1, dynamicg1ref)
(json, model, StaticG1, StaticG2, DynamicG1)
end

function run_preprocessor(modfile::String)
Expand Down Expand Up @@ -388,7 +385,7 @@ function compose_derivatives(model)

# Static Jacobian
staticg1ref = Dict{Tuple{Int64, String}, SymEngine.Basic}()
I, J, V = Array{Int,1}(), Array{Int,1}(), Array{SymEngine.Basic,1}()
I, J, V = Array{Int,1}(), Array{Int,1}(), String("[")
for i = 1:nendog
for eq in model["static_xrefs"][model["endogenous"][i].name]
sederiv = SymEngine.diff(model["static"][eq],
Expand All @@ -397,17 +394,16 @@ function compose_derivatives(model)
staticg1ref[(eq, model["endogenous"][i].name)] = sederiv
I = [I; eq]
J = [J; i]
V = [V; replace_all_symengine_symbols(sederiv, endos, exos, params)]
V *= (V == "[" ? "" : ";") * string(replace_all_symengine_symbols(sederiv, endos, exos, params))
end
end
end
staticg11 = sparse(I,J,V,nendog,nendog)
NumericFuns.evaluate(::StaticG1, endo::Array{Float64,1}, exo::Array{Float64,1}, param::Array{Float64,1}) =
sparse(:($I), :($J), [eval(d) for d in :($V)], :($nendog), :($nendog))
V = parse(V * "]")
StaticG1 = @eval (endo, exo, param) -> sparse($I, $J, $V, $nendog, $nendog)

# Static Hessian
staticg2ref = Dict{Tuple{Int64, String, String}, SymEngine.Basic}()
I, J, V = Array{Int,1}(), Array{Int,1}(), Array{SymEngine.Basic,1}()
I, J, V = Array{Int,1}(), Array{Int,1}(), String("[")
eqs = unique([ k[1] for k in keys(staticg1ref) ])
for i = 1:nendog
for eq in eqs
Expand All @@ -419,7 +415,7 @@ function compose_derivatives(model)
staticg2ref[(eq, model["endogenous"][i].name, model["endogenous"][i].name)] = sederiv
I = [I; eq]
J = [J; (i-1)*nendog+i]
V = [V; replace_all_symengine_symbols(sederiv, endos, exos, params)]
V *= (V == "[" ? "" : ";") * string(replace_all_symengine_symbols(sederiv, endos, exos, params))
end
for j = i+1:nendog
if any(eq .== model["static_xrefs"][model["endogenous"][j].name])
Expand All @@ -428,23 +424,23 @@ function compose_derivatives(model)
if sederiv != 0
staticg2ref[(eq, model["endogenous"][i].name, model["endogenous"][j].name)] = sederiv
staticg2ref[(eq, model["endogenous"][j].name, model["endogenous"][i].name)] = sederiv
deriv = replace_all_symengine_symbols(sederiv, endos, exos, params)
deriv = string(replace_all_symengine_symbols(sederiv, endos, exos, params))
I = [I; eq; eq]
J = [J; (i-1)*nendog+j; (j-1)*nendog+i]
V = [V; deriv; deriv]
V *= (V == "[" ? "" : ";") * deriv * ";" * deriv
end
end
end
end
end
end
NumericFuns.evaluate(::StaticG2, endo::Array{Float64,1}, exo::Array{Float64,1}, param::Array{Float64,1}) =
sparse(:($I), :($J), [eval(d) for d in :($V)], :($nendog), :($nendog)^2)
V = parse(V * "]")
StaticG2 = @eval (endo, exo, param) -> sparse($I, $J, $V, $nendog, $nendog^2)

# Dynamic Jacobian
col = 1
dynamicg1ref = Dict{Tuple{Int64, String}, SymEngine.Basic}()
I, J, V = Array{Int,1}(), Array{Int,1}(), Array{SymEngine.Basic,1}()
I, J, V = Array{Int,1}(), Array{Int,1}(), String("[")
endos = model["lead_lag_incidence_ref"]
exos = model["lead_lag_incidence_exo_ref"]
for ae in [ filter((k,v)->k[2] == i, model["dynamic_endog_xrefs"]) for i = -1:1 ]
Expand All @@ -456,7 +452,7 @@ function compose_derivatives(model)
dynamicg1ref[(eq, model["dynamic_endog_reverse_lookup"][tup[2][2]])] = sederiv
I = [I; eq]
J = [J; col]
V = [V; replace_all_symengine_symbols(sederiv, endos, exos, params)]
V *= (V == "[" ? "" : ";") * string(replace_all_symengine_symbols(sederiv, endos, exos, params))
end
end
col += 1
Expand All @@ -473,15 +469,15 @@ function compose_derivatives(model)
dynamicg1ref[(eq, model["dynamic_exog_reverse_lookup"][tup[2][2]])] = sederiv
I = [I; eq]
J = [J; col]
V = [V; replace_all_symengine_symbols(sederiv, endos, exos, params)]
V *= (V == "[" ? "" : ";") * string(replace_all_symengine_symbols(sederiv, endos, exos, params))
end
end
col += 1
end
end
end
NumericFuns.evaluate(::DynamicG1, endo::Array{Float64,1}, exo::Array{Float64,1}, param::Array{Float64,1}) =
sparse(:($I), :($J), [eval(d) for d in :($V)], :($nendog), :($ndynvars))
V = parse(V * "]")
DynamicG1 = @eval (endo, exo, param) -> sparse($I, $J, $V, $nendog, $ndynvars)

(staticg1ref, staticg2ref, dynamicg1ref)
(StaticG1, StaticG2, DynamicG1)
end

0 comments on commit b740765

Please sign in to comment.