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 = Unsafe.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 = Unsafe.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) = 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, false)) end | make_initial_vector (N,initial,SOME evinitial,NONE,NONE,extinitial,extevinitial) = Vector.tabulate (N, fn (i) => D.EventState (0.0, initial, evinitial, extinitial, extevinitial, false)) | make_initial_vector (N,initial,NONE,NONE,NONE,extinitial,extevinitial) = Vector.tabulate (N, fn (i) => D.ContState (0.0, initial, extinitial, extevinitial)) | 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, _, _, root), ext, extev) = D.RegimeState (x, y, ev, d, r, ext, extev, root) | update_external_state (D.EventState (x, y, ev, _, _, root), ext, extev) = D.EventState (x, y, ev, ext, extev, root) | update_external_state (D.ContState (x, y, _, _), ext, extev) = D.ContState (x, y, ext, extev) fun state_sub (D.RegimeState (x, y, ev, d, r, ext, extev, root), i) = getindex(y, i) | state_sub (D.EventState (x, y, ev, ext, extev, root), i) = getindex(y, i) | state_sub (D.ContState (x, y, ext, extev), i) = getindex(y, i) fun state_y (D.RegimeState (x, y, ev, d, r, ext, extev, root)) = y | state_y (D.EventState (x, y, ev, ext, extev, root)) = y | state_y (D.ContState (x, y, ext, extev)) = y fun state_indep (D.RegimeState (x, y, ev, d, r, ext, extev, root)) = x | state_indep (D.EventState (x, y, ev, ext, extev, root)) = x | state_indep (D.ContState (x, y, ext, extev)) = x fun state_ext (D.RegimeState (x, y, ev, d, r, ext, extev, root)) = ext | state_ext (D.EventState (x, y, ev, ext, extev, root)) = ext | state_ext (D.ContState (x, y, ext, extev)) = ext fun state_extev (D.RegimeState (x, y, ev, d, r, ext, extev, root)) = extev | state_extev (D.EventState (x, y, ev, ext, extev, root)) = extev | state_extev (D.ContState (x, y, ext, extev)) = extev fun state_regime (D.RegimeState (x, y, ev, d, r, ext, extev, root)) = r | state_regime (D.EventState (x, y, ev, ext, extev, root)) = Array.fromList [] | state_regime (D.ContState (x, y, ext, extev)) = Array.fromList[] fun state_event (D.RegimeState (x, y, ev, d, r, ext, extev, root)) = ev | state_event (D.EventState (x, y, ev, ext, extev, root)) = ev | state_event (D.ContState (x, y, ext, extev)) = Array.fromList [] fun ext_sub (D.RegimeState (x, y, ev, d, r, ext, extev, root), i) = getindex(ext, i) | ext_sub (D.EventState (x, y, ev, ext, extev, root), i) = getindex(ext, i) | ext_sub (D.ContState (x, y, ext, extev), i) = getindex(ext, i) fun event_sub (D.RegimeState (x, y, ev, d, r, ext, extev, root), i) = getindex(ev, i) | event_sub (D.EventState (x, y, ev, ext, extev, root), i) = getindex(ev, i) | event_sub (D.ContState (x, y, ext, extev), i) = (putStrLn TextIO.stdOut "event_sub:"; raise Domain) fun state_root (D.RegimeState (x, y, ev, d, r, ext, extev, root)) = root | state_root (D.EventState (x, y, ev, ext, extev, root)) = root | state_root (D.ContState (x, y, ext, extev)) = false exception Index val label = "{{group.name}}" val N = {{group.order}} (* total population size *) {% 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 = int (* Given a delay (positive real number), compute the priority given a time step *) fun delayPriority (delay) = Real.round (Real./ (delay, h)) (* Given a priority and a time step, computes the corresponding delay *) fun priorityDelay (priority,h) = Real.* (Real.fromInt priority, h) fun compare (x,y) = Int.compare (x,y) type item = real * (int * (real IntMap.map)) fun priority (x : item) = delayPriority (#1(x)) end structure TEQ = FixTEventQueue (structure P = TEventPriority type value = (int * (real IntMap.map)) 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 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 }} {% for pop in dict (group.populations) %} val {{pop.name}}_n0 = {{pop.value.start}} {% endfor %} 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) 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}}_ext_array = Array.array (List.length {{pop.name}}_ext_ports, 0.0) val {{pop.name}}_extev_array = Array.array (List.length {{pop.name}}_ext_ports, 0.0) 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,h) end fun {{pop.name}}_run (Wmap,n0) (i,input,(nstates,spikes)) = let (* {% if pop.value.prototype.fieldExprML %} val fieldV = getindex ({{pop.name}}_field_vector,i) {% endif %} *) val _ = if (i<{{group.statesample}}) then putStrLn (!{{pop.name}}_state_out) (Int.toString (i) ^ ", " ^ (showReal (state_indep input)) ^ ", " ^ (showRealArray (state_y input))) else () val _ = if (i<{{group.extsample}}) then putStrLn (!{{pop.name}}_ext_out) (Int.toString (i) ^ ", " ^ (showReal (state_indep input)) ^ ", " ^ (showRealArray (state_ext input)) ^ ", " ^ (showRealArray (state_extev input))) else () val input' = if state_root input then {{pop.name}}_f input else input val update = Unsafe.Array.update val ext_i = {{pop.name}}_ext_array val extev_i = {{pop.name}}_extev_array val _ = List.foldl (fn (port, index) => case IntMap.find (Wmap, port) of NONE => (update (ext_i, index, 0.0); update (extev_i, index, ~1.0); index+1) | SOME (t,W) => case IntMap.find(W,i+n0) of SOME v => (update (ext_i, index, v); update (extev_i, index, t); index+1) | NONE => (update (ext_i, index, 0.0); update (extev_i, index, ~1.0); index+1)) 0 {{pop.name}}_ext_ports val input'' = update_external_state (input', ext_i, extev_i) val nstate = {{pop.name}}_f input'' in (nstate::nstates, if (Real.>= (event_sub(nstate,0), 0.0)) then ((i+{{pop.name}}_n0,1.0))::spikes else spikes) 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 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 (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 ftime ( {% for pop in dict (group.populations) %} {{pop.name}}_state_vector{% if not loop.last %},{% endif %} {% endfor %} ) = {% with pop = first (dict (group.populations)) %} state_indep (Vector.sub ({{pop.name}}_state_vector,0)) {% endwith %} 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