structure {{group.name}} = struct structure D = Dynamics fun putStrLn out str = (TextIO.output (out, str); TextIO.output (out, "\n")) fun putStr out str = (TextIO.output (out, str)) fun showBoolean b = (if b then "1" else "0") fun showReal n = let open StringCvt open Real in (if n < 0.0 then "-" else "") ^ (fmt (FIX (SOME 12)) (abs n)) end fun showRealArray v = (String.concatWith ", " (Array.foldr (fn (x, ax) => (showReal x)::ax) [] v)) fun foldl1 f lst = let val v = List.hd lst val lst' = List.tl lst in List.foldl f v lst' end fun dimVals [m,n] = (m,n) | dimVals _ = raise SparseMatrix.Shape fun fromDiag (m, n, a, dflt) = if Index.validShape [m,n] then (let val na = RTensor.Array.length a val na' = na-1 val te = RTensor.new ([m,n], dflt) fun diag (i, j, ia) = let val ia' = (RTensor.update (te, [i,j], RTensor.Array.sub (a, ia)); if ia = na' then 0 else ia+1) in if (i=0) orelse (j=0) then te else diag (i-1, j-1, ia) end in diag (m-1, n-1, 0) end) else raise RTensor.Shape fun sampleN randomInt n dflt = let val i = ref 0 val sample = Array.array (n+1, dflt) val update = Array.update in (sample, fn (x) => (i := (!i)+1; if (!i) <= n then update (sample, !i, x) else (let val k = randomInt (0, !i) in if k < n then update(sample, randomInt (0, n), x) else () end))) end fun index_foldri (a, b, f, init) = if a <= b then index_foldri (a, b-1, f, f (b, init)) else init val getindex = Array.sub val RandomInit = RandomMTZig.fromEntropy val ZigInit = RandomMTZig.ztnew fun optApply fopt args = case fopt of SOME f => SOME (f args) | NONE => NONE fun make_initial_vector (N,initial,SOME evinitial,dinitial,SOME rinitial,extinitial,extevinitial,h0) = let val dinitial': real array = case dinitial of SOME v => v | NONE => (Array.fromList []) in Vector.tabulate (N, fn (i) => D.RegimeState (0.0, initial, evinitial, dinitial', rinitial, extinitial, extevinitial, h0, false)) end | make_initial_vector (N,initial,SOME evinitial,NONE,NONE,extinitial,extevinitial,h0) = Vector.tabulate (N, fn (i) => D.EventState (0.0, initial, evinitial, extinitial, extevinitial, h0, false)) | make_initial_vector (N,initial,NONE,NONE,NONE,extinitial,extevinitial,h0) = Vector.tabulate (N, fn (i) => D.ContState (0.0, initial, extinitial, extevinitial, h0)) | make_initial_vector (N,initial,_,_,_,extinitial,extevinitial,_) = (putStrLn TextIO.stdOut "make_initial_vector:"; raise Domain) fun update_external_state (D.RegimeState (x, y, ev, d, r, _, _, h, root), ext, extev) = D.RegimeState (x, y, ev, d, r, ext, extev, h, root) | update_external_state (D.EventState (x, y, ev, _, _, h, root), ext, extev) = D.EventState (x, y, ev, ext, extev, h, root) | update_external_state (D.ContState (x, y, _, _, h), ext, extev) = D.ContState (x, y, ext, extev, h) fun update_h (D.RegimeState (x, y, ev, d, r, ext, extev, _, root), h) = D.RegimeState (x, y, ev, d, r, ext, extev, h, root) | update_h (D.EventState (x, y, ev, ext, extev, _, root), h) = D.EventState (x, y, ev, ext, extev, h, root) | update_h (D.ContState (x, y, ext, extev, _), h) = D.ContState (x, y, ext, extev, h) fun state_sub (D.RegimeState (x, y, ev, d, r, ext, extev, h, root), i) = getindex(y, i) | state_sub (D.EventState (x, y, ev, ext, extev, h, root), i) = getindex(y, i) | state_sub (D.ContState (x, y, ext, extev, h), i) = getindex(y, i) fun state_y (D.RegimeState (x, y, ev, d, r, ext, extev, h, root)) = y | state_y (D.EventState (x, y, ev, ext, extev, h, root)) = y | state_y (D.ContState (x, y, ext, extev, h)) = y fun state_indep (D.RegimeState (x, y, ev, d, r, ext, extev, h, root)) = x | state_indep (D.EventState (x, y, ev, ext, extev, h, root)) = x | state_indep (D.ContState (x, y, ext, extev, h)) = x fun state_h (D.RegimeState (x, y, ev, d, r, ext, extev, h, root)) = h | state_h (D.EventState (x, y, ev, ext, extev, h, root)) = h | state_h (D.ContState (x, y, ext, extev, h)) = h fun state_ext (D.RegimeState (x, y, ev, d, r, ext, extev, h, root)) = ext | state_ext (D.EventState (x, y, ev, ext, extev, h, root)) = ext | state_ext (D.ContState (x, y, ext, extev, h)) = ext fun state_extev (D.RegimeState (x, y, ev, d, r, ext, extev, h, root)) = extev | state_extev (D.EventState (x, y, ev, ext, extev, h, root)) = extev | state_extev (D.ContState (x, y, ext, extev, h)) = extev fun state_regime (D.RegimeState (x, y, ev, d, r, ext, extev, h, root)) = r | state_regime (D.EventState (x, y, ev, ext, extev, h, root)) = Array.fromList [] | state_regime (D.ContState (x, y, ext, extev, h)) = Array.fromList[] fun state_event (D.RegimeState (x, y, ev, d, r, ext, extev, h, root)) = ev | state_event (D.EventState (x, y, ev, ext, extev, h, root)) = ev | state_event (D.ContState (x, y, ext, extev, h)) = Array.fromList [] fun ext_sub (D.RegimeState (x, y, ev, d, r, ext, extev, h, root), i) = getindex(ext, i) | ext_sub (D.EventState (x, y, ev, ext, extev, h, root), i) = getindex(ext, i) | ext_sub (D.ContState (x, y, ext, extev, h), i) = getindex(ext, i) fun event_sub (D.RegimeState (x, y, ev, d, r, ext, extev, h, root), i) = getindex(ev, i) | event_sub (D.EventState (x, y, ev, ext, extev, h, root), i) = getindex(ev, i) | event_sub (D.ContState (x, y, ext, extev, h), i) = (putStrLn TextIO.stdOut "event_sub:"; raise Domain) fun state_root (D.RegimeState (x, y, ev, d, r, ext, extev, h, root)) = root | state_root (D.EventState (x, y, ev, ext, extev, h, root)) = root | state_root (D.ContState (x, y, ext, extev, h)) = false exception Index val label = "{{group.name}}" val N = {{group.order}} (* total population size *) {% for pop in dict (group.populations) %} val {{pop.name}}_n0 = {{pop.value.start}} {% endfor %} {% if not (group.properties == []) %} {% for p in dict (group.properties) %} val {{p.name}} = {{p.value.exprML}} {% endfor %} {% endif %} val h = {{ timestep }} structure TEventPriority = struct type priority = real fun compare (x,y) = Real.compare (x,y) type item = real * (int * int * real) fun priority (x : item) = (#1(x)) end structure TEQ = TEventQueue (structure P = TEventPriority type value = (int * int * real) fun value (x : P.item) = (#2(x))) val DQ = TEQ.empty (* network propagation delays for each projection *) val D: real list = [{% for pr in dict (group.projections) %}{{pr.value.delay.exprML}}{% if not loop.last %},{% endif %}{% endfor %}] val minDelay = foldl1 Real.min D val seed_init = RandomInit() (* seed for randomized initial values *) val zt_init = ZigInit() fun random_normal () = RandomMTZig.randNormal(seed_init,zt_init) fun random_uniform () = RandomMTZig.randUniform(seed_init) fun random_uniform_vector () = RandomMTZig.randUniform(seed_init) fun random_int (imin,imax) = let val range = imax - imin in imin + Real.round(Real.* (Real.fromInt(range), RandomMTZig.randUniform(seed_init))) end {% for pop in dict (group.populations) %} val N_{{pop.name}} = {{ pop.value.size }} val {{pop.name}}_parameters = {{pop.value.prototype.name}}.paramfun() val {{pop.name}}_state_out = ref (TextIO.stdOut) val {{pop.name}}_ext_out = ref (TextIO.stdOut) (* val {{pop.name}}_field_vector = Vector.tabulate (N_{{pop.name}}, fn (i) => {{pop.value.prototype.name}}.fieldfun({{pop.name}}_parameters)) *) val {{pop.name}}_initial_vector = let val initial = {{pop.value.prototype.name}}.initfun({{pop.name}}_parameters) val evinitial = optApply {{pop.value.prototype.name}}.initcondfun () val dinitial = optApply {{pop.value.prototype.name}}.dinitfun () val rinitial = optApply {{pop.value.prototype.name}}.initregfun () val extinitial = {{pop.value.prototype.name}}.initextfun () val extevinitial = {{pop.value.prototype.name}}.initextevfun () in make_initial_vector (N_{{pop.name}},initial,evinitial,dinitial,rinitial,extinitial,extevinitial,h) end val {{pop.name}}_ext_inputs = Array.length ({{pop.value.prototype.name}}.initextfun ()) val {{pop.name}}_extev_inputs = Array.length ({{pop.value.prototype.name}}.initextevfun ()) val {{pop.name}}_ext_ports = [{% for portspec in dict (group.projectionPorts) %}{% if portspec.name == pop.name %}{% for port in portspec.value %}{{port}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}{% endfor %}] val {{pop.name}}_f = let val p = {{pop.name}}_parameters in D.integral({{pop.value.prototype.name}}.odefun p, optApply {{pop.value.prototype.name}}.condfun p, optApply {{pop.value.prototype.name}}.posfun p, optApply {{pop.value.prototype.name}}.negfun p, optApply {{pop.value.prototype.name}}.dposfun p, {{pop.value.prototype.name}}.regfun) end fun {{pop.name}}_run (tend,Wmap,n0) (i,input,(nstates,spikes)) = let (* {% if pop.value.prototype.fieldExprML %} val fieldV = getindex ({{pop.name}}_field_vector,i) {% endif %} *) val update = Unsafe.Array.update val ext_i = state_ext input val extev_i = state_extev input val _ = List.foldl (fn (port, index) => case IntMap.find (Wmap, i+n0) of NONE => (update (ext_i, index, 0.0); update (extev_i, index, Real.posInf); index+1) | SOME (spm) => case IntMap.find (spm, port) of SOME (t,v) => (update (ext_i, index, v); update (extev_i, index, t); index+1) | NONE => (update (ext_i, index, 0.0); update (extev_i, index, Real.posInf); index+1)) 0 {{pop.name}}_ext_ports fun recur (nstate, spikes, ct) = let val _ = if (i<{{group.statesample}}) andalso Real.>(state_indep nstate, ct) then putStrLn (!{{pop.name}}_state_out) (Int.toString (i) ^ ", " ^ (showReal (state_indep nstate)) ^ ", " ^ (showRealArray (state_y nstate))) else () val _ = if (i<{{group.extsample}}) andalso Real.>(state_indep nstate, ct) then putStrLn (!{{pop.name}}_ext_out) (Int.toString (i) ^ ", " ^ (showReal (state_indep nstate)) ^ ", " ^ (showRealArray (state_ext nstate)) ^ ", " ^ (showRealArray (state_extev nstate))) else () val nstate = if state_root nstate then {{pop.name}}_f nstate else nstate in if Real.>=(state_indep nstate, tend) then (nstate::nstates, spikes) else let val h' = Real.min(tend-(state_indep nstate), state_h nstate) val nstate' = update_h (nstate, h') val nstate'' = {{pop.name}}_f nstate' val hasevent = Real.>= (event_sub(nstate'',0), 0.0) in recur (nstate'', if hasevent then ((i+{{pop.name}}_n0,state_indep nstate'',1.0))::spikes else spikes, state_indep nstate'') end end in recur (input, spikes, 0.0) end {% endfor %} {% if group.plastypes %}{% for pl in dict (group.plastypes) %} val {{pl.name}}_parameters: real array = {{pl.name}}.paramfun() val {{pl.name}}_initial = {{pl.name}}.initfun({{pl.name}}_parameters) {% endfor %}{% endif %} {% if group.conntypes %}{% for conn in dict (group.conntypes) %} {% if conn.value.sysFn %} val {{conn.name}}_initial = {{conn.value.initialExprML}} val {{conn.name}}_f = Model_{{conn.name}}.{{conn.value.sysFn}} {% endif %} {% endfor %}{% endif %} val initial = ( {% for pop in dict (group.populations) %} {{pop.name}}_initial_vector{% if not loop.last %},{% endif %} {% endfor %} ) val Pn = [ {% for pop in dict (group.populations) %} {{pop.name}}_n0{% if not loop.last %},{% endif %} {% endfor %} ] fun frun (tend,I) ( {% for pop in dict (group.populations) %} {{pop.name}}_state_vector{% if not loop.last %},{% endif %} {% endfor %} ) = let {% for pop in dict (group.populations) %} val ({{pop.name}}_states,{{pop.name}}_spikes) = Vector.foldri ({{pop.name}}_run (tend,I,{{pop.name}}_n0)) ([],[]) {{pop.name}}_state_vector {% endfor %} in (( {% for pop in dict (group.populations) %} Vector.fromList {{pop.name}}_states{% if not loop.last %},{% endif %} {% endfor %} ), ( {% for pop in dict (group.populations) %} {{pop.name}}_spikes{% if not loop.last %},{% endif %} {% endfor %} )) end fun fspikes ( {% for pop in dict (group.populations) %} {{pop.name}}_spike_i{% if not loop.last %},{% endif %} {% endfor %} ) = let val ext_spike_i = List.concat ( {% for pop in dict (group.populations) %}{% if not pop.name in group.spikepoplst %}{{pop.name}}_spike_i ::{% endif %}{% endfor %} [] ) val neuron_spike_i = List.concat [ {% for name in (group.spikepoplst) %} {{name}}_spike_i{% if not loop.last %},{% endif %} {% endfor %} ] val all_spike_i = List.concat [neuron_spike_i, ext_spike_i] in (all_spike_i, neuron_spike_i) end {% macro cartesian_product(sp, tp) %} {% for s,t in allCombs(sp,tp) %} {{ caller(s,t) }}{% if not loop.last %},{% endif %} {% endfor %} {% endmacro %} {% macro for_each(name, sp, tp, plasticity, component, cstate) %} val Pr_{{name}} = let val weight = {% if plasticity %}getindex({{plasticity}}_initial,0){% else %}1.0{% endif %} in SparseMatrix.fromGeneratorList [N,N] [ {% call cartesian_product (sp,tp) %}{offset=[{{t.start}},{{s.start}}], fshape=[{{t.size}},{{s.size}}], f=(fn (i) => Real.* (weight, #{{cstate}}({{component}}_f {{component}}_initial) ))}{% endcall %} ] end {% endmacro %} {% macro all_to_all(name, sp, tp, plasticity) %} val Pr_{{name}} = let val weight = {% if plasticity %}getindex({{plasticity}}_initial,0){% else %}1.0{% endif %} in SparseMatrix.fromTensorList [N,N] [ {% call cartesian_product (sp,tp) %}{offset=[{{t.start}},{{s.start}}], tensor=(RTensor.*> weight (RTensor.new ([{{t.size}},{{s.size}}],1.0))), sparse=false}{% endcall %} ] end {% endmacro %} {% macro one_to_one(name, sp, tp, plasticity) %} val Pr_{{name}} = let val weight = {% if plasticity %}getindex({{plasticity}}_initial,0){% else %}1.0{% endif %} in SparseMatrix.fromTensorList [N,N] [ {% call cartesian_product (sp,tp) %}{offset=[{{t.start}},{{s.start}}], tensor=(fromDiag ({{t.size}},{{s.size}},Real64Array.fromList [weight],0.0)), sparse=true}{% endcall %} ] end {% endmacro %} {% macro from_file(name, sp, tp, filename) %} val Pr_{{name}} = let val infile = TextIO.openIn "{{filename}}" val S = TensorFile.realTensorRead (infile) val _ = TextIO.closeIn infile in SparseMatrix.fromTensorSliceList [N,N] [ {% with %} {% set soffset = 0 %} {% for s in sp %} {% set toffset = 0 %} {% for t in tp %} {offset=[{{t.start}},{{s.start}}], slice=(RTensorSlice.slice ([([{{toffset}},{{soffset}}],[{{toffset}}+{{t.size}}-1,{{soffset}}+{{s.size}}-1])],S)), sparse=false}{% if not loop.last %},{% endif %} {% set toffset = toffset + t.size %} {% endfor %}{% if not loop.last %},{% endif %} {% set soffset = soffset + s.size %} {% endfor %} {% endwith %} ] end {% endmacro %} {% macro preorder(sp, tp) %} {% for s in sp %} {% for t in tp %} {{ caller(s,t) }}{% if not loop.last %},{% endif %} {% endfor %}{% if not loop.last %},{% endif %} {% endfor %} {% endmacro %} {% macro postorder(sp, tp) %} {% for t in tp %} {% for s in sp %} {{ caller(s,t) }}{% if not loop.last %},{% endif %} {% endfor %}{% if not loop.last %},{% endif %} {% endfor %} {% endmacro %} {% macro random_fan_in(name, sp, tp, plasticity, prob) %} val Pr_{{name}} = let val weight = {% if plasticity %}getindex({{plasticity}}_initial,0){% else %}1.0{% endif %} val f = (fn (i) => if (Real.> ({{prob}}, random_uniform ())) then weight else 0.0) in SparseMatrix.fromGeneratorList [N,N] [ {% call postorder (sp,tp) %} {offset=[{{t.start}},{{s.start}}], fshape=[{{t.size}},{{s.size}}], f=f}{% endcall %} ] end {% endmacro %} {% macro random_fan_out(name, sp, tp, plasticity, prob) %} val Pr_{{name}} = let val weight = {% if plasticity %}getindex({{plasticity}}_initial,0){% else %}1.0{% endif %} val f = (fn (i) => if (Real.> ({{prob}}, random_uniform())) then weight else 0.0) in SparseMatrix.fromGeneratorList [N,N] [ {% call preorder (sp,tp) %} {offset=[{{t.start}},{{s.start}}], fshape=[{{t.size}},{{s.size}}], f=f}{% endcall %} ] end {% endmacro %} {% macro random_fan_in_num(name, sp, tp, plasticity, num) %} val Pr_{{name}} = let val weight = {% if plasticity %}getindex({{plasticity}}_initial,0){% else %}1.0{% endif %} in SparseMatrix.fromVectors [N,N] [ {% call postorder (sp,tp) %} (let val sample = Array.array (Int.min({{num}},{{s.size}}) * {{t.size}}, (0,0,0.0)) val update = Unsafe.Array.update val _ = Loop.foldi (0,{{t.size}}, fn (i,k) => Loop.foldi (0,{{num}}, fn (j,k) => (update (sample,k,(i,random_int (0, {{s.size}}-1),weight)); k+1), k), 0) val v = Array.vector sample in {offset=[{{t.start}},{{s.start}}], v=v, shape_v=[{{t.size}},{{s.size}}]} end){% endcall %} ] end {% endmacro %} {% macro random_fan_out_num(name, sp, tp, plasticity, num) %} val Pr_{{name}} = let val weight = {% if plasticity %}getindex({{plasticity}}_initial,0){% else %}1.0{% endif %} in SparseMatrix.fromVectors [N,N] [ {% call preorder (sp,tp) %} (let val sample = Array.array (Int.min({{num}},{{s.size}}) * {{t.size}}, (0,0,0.0)) val update = Unsafe.Array.update val _ = Loop.foldi (0,{{t.size}}, fn (i,k) => Loop.foldi (0,{{num}}, fn (j,k) => (update (sample,k,(i,random_int (0, {{s.size}}-1),weight)); k+1), k), 0) val v = Array.vector sample in {offset=[{{t.start}},{{s.start}}], v=v, shape_v=[{{t.size}},{{s.size}}]} end){% endcall %} ] end {% endmacro %} {% macro range_map(name, sp, tp) %} val srangemap_{{name}} = [ {% with %} {% set soffset = 0 %} {% for s in sp %} {size={{s.size}} localStart={{soffset}}, globalStart={{s.start}} }{% if not loop.last %},{% endif %} {% set soffset = soffset + s.size %} {% endfor %} {% endwith %} ] val trangemap_{{name}} = [ {% with %} {% set toffset = 0 %} {% for t in tp %} {size={{t.size}} localStart={{toffset}}, globalStart={{t.start}} }{% if not loop.last %},{% endif %} {% set toffset = toffset + t.size %} {% endfor %} {% endwith %} ] {% endmacro %} fun fprojection () = (let {% for pr in dict (group.projections) %} val _ = putStrLn TextIO.stdOut "constructing {{pr.name}}" {% if pr.value.connectivity.type.sysFn %} {% call for_each(pr.name, pr.value.source.populations, pr.value.destination.populations, pr.value.plasticity, pr.value.connectivity.name, pr.value.connectivity.port) %} {% endcall %} {% elseif pr.value.connectivity.type.stdlib == "OneToOne" %} {% call one_to_one(pr.name, pr.value.source.populations, pr.value.destination.populations, pr.value.plasticity) %} {% endcall %} {% elseif pr.value.connectivity.type.stdlib == "AllToAll" %} {% call all_to_all(pr.name, pr.value.source.populations, pr.value.destination.populations, pr.value.plasticity) %} {% endcall %} {% elseif pr.value.connectivity.type.stdlib == "FromFile" %} {% call from_file(pr.name, pr.value.source.populations, pr.value.destination.populations, pr.value.rule.properties.filename.exprML) %} {% endcall %} {% elseif pr.value.connectivity.type.stdlib == "RandomFanIn" && pr.value.connectivity.type.probability %} {% call random_fan_in(pr.name, pr.value.source.populations, pr.value.destination.populations, pr.value.plasticity, pr.value.connectivity.type.probability) %} {% endcall %} {% elseif pr.value.connectivity.type.stdlib == "RandomFanIn" && pr.value.connectivity.type.number %} {% call random_fan_in_num(pr.name, pr.value.source.populations, pr.value.destination.populations, pr.value.plasticity, pr.value.connectivity.type.number) %} {% endcall %} {% elseif pr.value.connectivity.type.stdlib == "RandomFanOut" && pr.value.connectivity.type.probability %} {% call random_fan_out(pr.name, pr.value.source.populations, pr.value.destination.populations, pr.value.plasticity, pr.value.connectivity.type.probability) %} {% endcall %} {% elseif pr.value.connectivity.type.stdlib == "RandomFanOut" && pr.value.connectivity.type.number %} {% call random_fan_out(pr.name, pr.value.source.populations, pr.value.destination.populations, pr.value.plasticity, pr.value.connectivity.type.number) %} {% endcall %} {% endif %} {% endfor %} val S = ([ {% for pr in dict (group.projections) %} {% if pr.value.type == "event" %} Pr_{{pr.name}}{% if not loop.last %},{% endif %} {% endif %} {% endfor %} ]) {% for pr in dict (group.projections) %} {% if pr.value.type == "continuous" %} {% call range_map(pr.name, pr.value.source.populations, pr.value.destination.populations) %} {% endcall %} {% endif %} {% endfor %} val Elst = [ {% for pr in dict (group.projections) %} {% if pr.value.type == "continuous" %} ElecGraph.junctionMatrix ([N,N],ElecGraph.elecGraph ({{pr.name}}(srangemap_{{pr.name}},trangemap_{{pr.name}})) Pr_{{pr.name}}){% if not loop.last %},{% endif %} {% endif %} {% endfor %} ] val E = if List.null Elst then NONE else SOME Elst in S end) end