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 fun assoc ((k,v)::rst) x = if k=x then SOME v else assoc rst x | assoc [] x = NONE fun member (k,lst) = case List.find (fn(x)=>k=x) lst of SOME _ => true | NONE => false 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 condfun (N,initial,SOME evinitial,dinitial,SOME rinitial,extinitial,extevinitial, alloc,bool_alloc,n,nev,ndsc,nregime) = let val dinitial': real array -> real array = case dinitial of SOME v => v | NONE => (fn v => v) in Vector.tabulate (N, fn (i) => D.condApply condfun (D.RegimeState (0.0, initial(alloc n), 0.0, evinitial (alloc nev), dinitial' (alloc ndsc), rinitial (bool_alloc nregime), extinitial(), extevinitial(), alloc n, alloc n, alloc nev, false))) end | make_initial_vector condfun (N,initial,SOME evinitial,NONE,NONE,extinitial,extevinitial, alloc,bool_alloc,n,nev,ndsc,nregime) = Vector.tabulate (N, fn (i) => D.condApply condfun (D.EventState (0.0, initial(alloc n), 0.0, evinitial (alloc nev), extinitial (), extevinitial (), initial(alloc n), initial(alloc n), alloc nev, false))) | make_initial_vector condfun (N,initial,NONE,NONE,NONE,extinitial,extevinitial, alloc,bool_alloc,n,nev,ndsc,nregime) = Vector.tabulate (N, fn (i) => D.ContState (0.0, initial(alloc n), extinitial(), extevinitial(), alloc n, alloc n)) | make_initial_vector condfun (N,initial,_,_,_,extinitial,extevinitial,_,_,_,_,_,_) = (putStrLn TextIO.stdOut "make_initial_vector:"; raise Domain) fun state_sub (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root), i) = getindex(y, i) | state_sub (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root), i) = getindex(y, i) | state_sub (D.ContState (x, y, ext, extev, ynext, yrsp), i) = getindex(y, i) fun state_y (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root)) = y | state_y (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root)) = y | state_y (D.ContState (x, y, ext, extev, ynext, yrsp)) = y fun state_indep (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root)) = x | state_indep (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root)) = x | state_indep (D.ContState (x, y, ext, extev, ynext, yrsp)) = x fun state_ext (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root)) = ext | state_ext (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root)) = ext | state_ext (D.ContState (x, y, ext, extev, ynext, yrsp)) = ext fun state_extev (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root)) = extev | state_extev (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root)) = extev | state_extev (D.ContState (x, y, ext, extev, ynext, yrsp)) = extev fun state_regime (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root)) = r | state_regime (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root)) = Array.fromList [] | state_regime (D.ContState (x, y, ext, extev, ynext, yrsp)) = Array.fromList[] fun state_event (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root)) = ev | state_event (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root)) = ev | state_event (D.ContState (x, y, ext, extev, ynext, yrsp)) = Array.fromList [] fun ext_sub (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root), i) = getindex(ext, i) | ext_sub (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root), i) = getindex(ext, i) | ext_sub (D.ContState (x, y, ext, extev, ynext, yrsp), i) = getindex(ext, i) fun event_sub (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root), i) = getindex(ev, i) | event_sub (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root), i) = getindex(ev, i) | event_sub (D.ContState (x, y, ext, extev, ynext, yrsp), i) = (putStrLn TextIO.stdOut "event_sub:"; raise Domain) fun state_root (D.RegimeState (x, y, xev, ev, d, r, ext, extev, ynext, yrsp, enext, root)) = root | state_root (D.EventState (x, y, xev, ev, ext, extev, ynext, yrsp, enext, root)) = root | state_root (D.ContState (x, y, ext, extev, ynext, yrsp)) = false exception Index exception InvalidPopulationSet of string 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 %} (* 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 }} val {{pop.name}}_n0 = {{pop.value.start}} 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}}_event_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 = {{pop.value.prototype.name}}.initcondfun val dinitial = {{pop.value.prototype.name}}.dinitfun val rinitial = {{pop.value.prototype.name}}.initregfun val extinitial = {{pop.value.prototype.name}}.initextfun ({{pop.name}}_parameters) val extevinitial = {{pop.value.prototype.name}}.initextevfun ({{pop.name}}_parameters) in make_initial_vector (optApply {{pop.value.prototype.name}}.condfun ({{pop.name}}_parameters)) (N_{{pop.name}},initial,evinitial,dinitial,rinitial,extinitial,extevinitial, {{pop.value.prototype.name}}.alloc,{{pop.value.prototype.name}}.bool_alloc, {{pop.value.prototype.name}}.n,{{pop.value.prototype.name}}.nev,{{pop.value.prototype.name}}.ndsc, {{pop.value.prototype.name}}.nregime) end 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 %}] fun {{pop.name}}_f h = 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 f (statesample,extsample,evsample) (Wmap,n0) (i,input,(nstates,spikes)) = let fun log (nstate) = let val _ = if (i case IntMap.find (Wmap, port) of NONE => (update (ext_i, index, 0.0); update (extev_i, index, Real.posInf); 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, Real.posInf); index+1)) 0 {{pop.name}}_ext_ports fun recur (nstate,spikes) = let val spikes' = if (Real.>= (event_sub(nstate,0), 0.0)) then ((i+{{pop.name}}_n0,1.0))::spikes else spikes in if state_root nstate then (log nstate; recur (f nstate, spikes')) else (nstate,spikes') end val _ = log(input) val (nstate,spikes') = recur (f input,spikes) in (nstate::nstates, spikes') end {% endfor %} val popmap = [ {% for s in dict (group.sets) %} ("{{s.name}}"{% for p in s.value.populations %}::"{{p.name}}"{% endfor %}::[]){% if not loop.last %},{% endif %} {% 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 (statesample,extsample,evsample) h 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 ({{pop.name}}_f h) (statesample,extsample,evsample) (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 fspikeidxs spikesetName = let val spikesetPops = case List.find (fn(x) => spikesetName = (hd x)) popmap of SOME lst => tl lst | NONE => raise InvalidPopulationSet spikesetName val pops = [{% for pop in dict (group.populations) %}"{{pop.name}}"{% if not loop.last %},{% endif %}{% endfor %}] val popIdxs = ListPair.zip (pops, List.tabulate (List.length pops, fn (i) => i)) in List.map (valOf o assoc popIdxs) spikesetPops end fun fspikes spikelogIdxs ( {% for pop in dict (group.populations) %} {{pop.name}}_spike_i{% if not loop.last %},{% endif %} {% endfor %} ) = let val all_spike_i = [{% for pop in dict (group.populations) %}{{pop.name}}_spike_i{% if not loop.last %},{% endif %}{% endfor %}] val labeled_spike_i = ListPair.zip (List.tabulate (List.length all_spike_i, fn (i) => i), all_spike_i) val (log_spike_i,ext_spike_i) = List.partition (fn(i,x) => member (i, spikelogIdxs)) labeled_spike_i in (all_spike_i, List.map #2 log_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({{plasticity}}.alloc {{plasticity}}.n),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({{plasticity}}.alloc {{plasticity}}.n),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({{plasticity}}.alloc {{plasticity}}.n),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({{plasticity}}.alloc {{plasticity}}.n),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({{plasticity}}.alloc {{plasticity}}.n),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({{plasticity}}.alloc {{plasticity}}.n),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({{plasticity}}.alloc {{plasticity}}.n),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