yinspire 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +24 -0
- data/bench/pq/Makefile +5 -0
- data/bench/pq/bench.cc +321 -0
- data/bench/pq/bench.rb +125 -0
- data/bench/pq/bench_binaryheap.h +46 -0
- data/bench/pq/bench_calendarqueue.h +58 -0
- data/bench/pq/bench_pairingheap.h +61 -0
- data/bench/pq/bench_stlpq.h +46 -0
- data/bench/pq/benchmark.h +225 -0
- data/bench/pq/distribution.h +93 -0
- data/bench/pq/make.rb +24 -0
- data/bin/yinspire +186 -0
- data/examples/nets/gereon2005.c.json +93723 -0
- data/examples/nets/gereon2005.yin +232650 -0
- data/examples/nets/skorpion.graphml +396 -0
- data/examples/nets/spiketrains_angle_180.txt +8 -0
- data/lib/Algorithms/Array.h +52 -0
- data/lib/Algorithms/BinaryHeap.h +265 -0
- data/lib/Algorithms/CalendarQueue.h +257 -0
- data/lib/Algorithms/IndexedBinaryHeap.h +90 -0
- data/lib/Algorithms/PairingHeap.h +169 -0
- data/lib/Allocators/ChunkedFreelistAllocator.h +96 -0
- data/lib/Allocators/MemoryAllocator.h +45 -0
- data/lib/Allocators/RubyMemoryAllocator.h +37 -0
- data/lib/Yinspire.rb +69 -0
- data/lib/Yinspire/All.rb +10 -0
- data/lib/Yinspire/Core/NeuralEntity.rb +133 -0
- data/lib/Yinspire/Core/Neuron.rb +162 -0
- data/lib/Yinspire/Core/Scheduling/NeuralEntity.rb +123 -0
- data/lib/Yinspire/Core/Scheduling/Simulator.rb +94 -0
- data/lib/Yinspire/Core/Simulator.rb +36 -0
- data/lib/Yinspire/Core/StimuliMixin.rb +103 -0
- data/lib/Yinspire/Core/Stimulus.rb +25 -0
- data/lib/Yinspire/Core/Synapse.rb +64 -0
- data/lib/Yinspire/Dumpers/Dumper.rb +19 -0
- data/lib/Yinspire/Dumpers/Dumper_Dot.rb +28 -0
- data/lib/Yinspire/Loaders/GraphML.rb +84 -0
- data/lib/Yinspire/Loaders/Loader.rb +31 -0
- data/lib/Yinspire/Loaders/Loader_GraphML.rb +97 -0
- data/lib/Yinspire/Loaders/Loader_JSON.rb +181 -0
- data/lib/Yinspire/Loaders/Loader_Spike.rb +42 -0
- data/lib/Yinspire/Loaders/Loader_Yin.rb +62 -0
- data/lib/Yinspire/Loaders/YinScanner.rb +247 -0
- data/lib/Yinspire/Models/Neuron_Base.rb +38 -0
- data/lib/Yinspire/Models/Neuron_Input.rb +12 -0
- data/lib/Yinspire/Models/Neuron_InputOutput.rb +39 -0
- data/lib/Yinspire/Models/Neuron_Output.rb +15 -0
- data/lib/Yinspire/Models/Neuron_SRM01.rb +50 -0
- data/lib/Yinspire/Models/Neuron_SRM02.rb +64 -0
- data/lib/Yinspire/Models/Synapse_Hebb.rb +67 -0
- data/pure_cpp/Makefile +22 -0
- data/pure_cpp/README +2 -0
- data/pure_cpp/src/algo/binary_heap.h +277 -0
- data/pure_cpp/src/algo/indexed_binary_heap.h +90 -0
- data/pure_cpp/src/json/json.cc +542 -0
- data/pure_cpp/src/json/json.h +182 -0
- data/pure_cpp/src/json/json_parser.cc +685 -0
- data/pure_cpp/src/json/json_parser.h +15 -0
- data/pure_cpp/src/json/json_parser.rl +213 -0
- data/pure_cpp/src/main.cc +49 -0
- data/pure_cpp/src/memory_allocator.h +45 -0
- data/pure_cpp/src/neural_entity.cc +208 -0
- data/pure_cpp/src/neural_entity.h +243 -0
- data/pure_cpp/src/neuron.cc +136 -0
- data/pure_cpp/src/neuron.h +70 -0
- data/pure_cpp/src/neuron_srm_01.cc +77 -0
- data/pure_cpp/src/neuron_srm_01.h +36 -0
- data/pure_cpp/src/simulator.cc +151 -0
- data/pure_cpp/src/simulator.h +116 -0
- data/pure_cpp/src/synapse.cc +117 -0
- data/pure_cpp/src/synapse.h +60 -0
- data/pure_cpp/src/types.h +18 -0
- data/run.rb +68 -0
- data/tools/conv_jsonc_to_yin.rb +165 -0
- data/tools/converter.rb +93 -0
- data/tools/json_writer.rb +122 -0
- data/yinspire.gemspec +20 -0
- metadata +156 -0
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'Yinspire/Loaders/Loader'
|
2
|
+
require 'yaml' # YAML is a superset of JSON
|
3
|
+
|
4
|
+
class Loader_JSON < Loader
|
5
|
+
|
6
|
+
def load(filename)
|
7
|
+
@entities = Hash.new
|
8
|
+
data = YAML.load(File.read(filename))
|
9
|
+
|
10
|
+
case data['format']
|
11
|
+
when 'yinspire.1'
|
12
|
+
load_v1(data)
|
13
|
+
when 'yinspire.c'
|
14
|
+
load_c(data)
|
15
|
+
else
|
16
|
+
raise "invalid format"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
#
|
23
|
+
# Format:
|
24
|
+
#
|
25
|
+
# {
|
26
|
+
# templates: {
|
27
|
+
# 'MyNeuron' => ['Neuron_SRM01', {tau_m: 0.5, :ref_weight: 0.1}],
|
28
|
+
# 'MySynapse' => ['Synapse', {weight: 1.0, delay: 0.5}]
|
29
|
+
# },
|
30
|
+
# entities: {
|
31
|
+
# 'id1' => ['MyNeuron', {tau_m: 5.1, const_threshold: 0.44}],
|
32
|
+
# 'id2' => ['Neuron_SRM01', {}],
|
33
|
+
# 'id3' => ['MySynapse'],
|
34
|
+
# 'id4' => 'MyNeuron'
|
35
|
+
# },
|
36
|
+
# connections: {
|
37
|
+
# 'id1' => ['id2', 'id3'],
|
38
|
+
# 'id2' => ['id1']
|
39
|
+
# },
|
40
|
+
# events: {
|
41
|
+
# 'id1' => [100.0, 101.0, timestamp_x, timestamp_y],
|
42
|
+
# 'id2' => [444, 555]
|
43
|
+
# }
|
44
|
+
# }
|
45
|
+
#
|
46
|
+
# Every "section" is optional.
|
47
|
+
#
|
48
|
+
def load_v1(data)
|
49
|
+
templates = data['templates'] || {}
|
50
|
+
entities = data['entities'] || {}
|
51
|
+
connections = data['connections'] || {}
|
52
|
+
events = data['events'] || {}
|
53
|
+
|
54
|
+
#
|
55
|
+
# construct entities
|
56
|
+
#
|
57
|
+
hash = Hash.new
|
58
|
+
entities.each do |id, entity_spec|
|
59
|
+
type, data = *entity_spec
|
60
|
+
|
61
|
+
if t = templates[type]
|
62
|
+
type, template_data = *t
|
63
|
+
hash.update(template_data) if template_data
|
64
|
+
end
|
65
|
+
|
66
|
+
hash.update(data) if data
|
67
|
+
|
68
|
+
create_entity(type, id, hash)
|
69
|
+
|
70
|
+
hash.clear
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# connect them
|
75
|
+
#
|
76
|
+
connections.each do |src, destinations|
|
77
|
+
entity = @entities[src]
|
78
|
+
destinations.each do |dest|
|
79
|
+
entity.connect(@entities[dest])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# stimulate with events
|
85
|
+
#
|
86
|
+
events.each do |id, time_series|
|
87
|
+
entity = @entities[id]
|
88
|
+
time_series.each do |at|
|
89
|
+
entity.stimulate(at, Infinity, nil)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# This is a version for the pure C++ version of Yinspire. It doesn't
|
96
|
+
# use hashes for entities and connections (because the C++ JSON library
|
97
|
+
# does not implement efficient hash lookup).
|
98
|
+
#
|
99
|
+
# {
|
100
|
+
# templates: {
|
101
|
+
# 'MyNeuron' => ['Neuron_SRM01', {tau_m: 0.5, :ref_weight: 0.1}],
|
102
|
+
# 'MySynapse' => ['Synapse', {weight: 1.0, delay: 0.5}]
|
103
|
+
# },
|
104
|
+
# entities: [
|
105
|
+
# ['id1', 'MyNeuron'],
|
106
|
+
# ['id2', 'Neuron_SRM01'],
|
107
|
+
# ['id3', 'MySynapse'],
|
108
|
+
# ['id4', 'MyNeuron']
|
109
|
+
# ],
|
110
|
+
# connections: {
|
111
|
+
# ['id1', 'id2', 'id3'],
|
112
|
+
# ['id2', 'id1']
|
113
|
+
# },
|
114
|
+
# events: {
|
115
|
+
# 'id1' => [100.0, 101.0, timestamp_x, timestamp_y],
|
116
|
+
# 'id2' => [444, 555]
|
117
|
+
# }
|
118
|
+
# }
|
119
|
+
#
|
120
|
+
# Every "section" is optional.
|
121
|
+
#
|
122
|
+
# BUGS:
|
123
|
+
#
|
124
|
+
# The C++ version does not currently implement to specify an
|
125
|
+
# entity like this:
|
126
|
+
#
|
127
|
+
# ['id1', 'Neuron_SRM01', {...}]
|
128
|
+
#
|
129
|
+
def load_c(data)
|
130
|
+
templates = data['templates'] || {}
|
131
|
+
entities = data['entities'] || []
|
132
|
+
connections = data['connections'] || []
|
133
|
+
events = data['events'] || {}
|
134
|
+
|
135
|
+
#
|
136
|
+
# construct entities
|
137
|
+
#
|
138
|
+
hash = Hash.new
|
139
|
+
entities.each do |arr|
|
140
|
+
hash.clear
|
141
|
+
|
142
|
+
id, type, data = *arr
|
143
|
+
|
144
|
+
if t = templates[type]
|
145
|
+
type, template_data = *t
|
146
|
+
hash.update(template_data)
|
147
|
+
end
|
148
|
+
|
149
|
+
if data
|
150
|
+
hash.update(data)
|
151
|
+
raise # FIXME: C++ version is invalid, because it assume that there
|
152
|
+
# is no data!
|
153
|
+
end
|
154
|
+
|
155
|
+
create_entity(type, id, hash)
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# connect them
|
160
|
+
#
|
161
|
+
connections.each do |arr|
|
162
|
+
src, *destinations = *arr
|
163
|
+
raise if destinations.empty?
|
164
|
+
entity = @entities[src] || raise
|
165
|
+
destinations.each do |dest|
|
166
|
+
entity.connect(@entities[dest] || raise)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# stimulate with events
|
172
|
+
#
|
173
|
+
events.each do |id, time_series|
|
174
|
+
entity = @entities[id] || raise
|
175
|
+
time_series.each do |at|
|
176
|
+
entity.stimulate(at, Infinity, nil)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'Yinspire/Loaders/Loader'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Loader for spikes in the format:
|
5
|
+
#
|
6
|
+
# Id1 weight1@time1 time2 time3 ...
|
7
|
+
# Id2 time1 time2 time3 ...
|
8
|
+
# ...
|
9
|
+
#
|
10
|
+
# Weight values (e.g. 1.0@time1) are optional.
|
11
|
+
#
|
12
|
+
# Lines beginning with "#" are comments.
|
13
|
+
#
|
14
|
+
class Loader_Spike < Loader
|
15
|
+
|
16
|
+
def load(filename)
|
17
|
+
File.open(filename, 'r') do |f|
|
18
|
+
while line = f.gets
|
19
|
+
line.strip!
|
20
|
+
next if line =~ /^#/ # comment
|
21
|
+
|
22
|
+
#
|
23
|
+
# The following code is to help Matlab to generate spike trains
|
24
|
+
# more easily and allows spaces before and after the "@", e.g.
|
25
|
+
# "123 @ 444".
|
26
|
+
#
|
27
|
+
line.gsub!(/\s+@\s+/, '')
|
28
|
+
|
29
|
+
id, *spikes = line.split
|
30
|
+
raise if spikes.empty?
|
31
|
+
entity = @entities[id] || raise
|
32
|
+
|
33
|
+
spikes.each do |spike|
|
34
|
+
weight, at = spike.split("@")
|
35
|
+
weight, at = Infinity, weight if at.nil? # spike is a pure time-value
|
36
|
+
entity.stimulate(at.to_f, weight.to_f, nil)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'Yinspire/Loaders/Loader'
|
2
|
+
require 'Yinspire/Loaders/YinScanner'
|
3
|
+
|
4
|
+
#
|
5
|
+
# This is a human readable data format for describing neural nets
|
6
|
+
# as well as stimulations.
|
7
|
+
#
|
8
|
+
# Note that it is a streaming scanner/parser, i.e. it's important
|
9
|
+
# to put the template definitions before you actually use them.
|
10
|
+
# The same applies to stimulations and connections!
|
11
|
+
#
|
12
|
+
class Loader_Yin < Loader
|
13
|
+
require 'enumerator'
|
14
|
+
|
15
|
+
def load(filename)
|
16
|
+
templates = {}
|
17
|
+
hash = Hash.new
|
18
|
+
YinScanner.new(File.read(filename)).scan do |cmd|
|
19
|
+
case cmd.shift
|
20
|
+
when :entity
|
21
|
+
ids, type, prop_list = *cmd
|
22
|
+
|
23
|
+
hash.clear
|
24
|
+
if t = templates[type]
|
25
|
+
type, template_data = *t
|
26
|
+
hash.update(template_data) if template_data
|
27
|
+
end
|
28
|
+
hash.update(prop_list) if prop_list
|
29
|
+
|
30
|
+
ids.each {|id| create_entity(type, id, hash) }
|
31
|
+
when :connect
|
32
|
+
cmd.first.each_cons(2) do |from, to|
|
33
|
+
from.each {|f|
|
34
|
+
entity = @entities[f]
|
35
|
+
to.each {|t| entity.connect(@entities[t]) }
|
36
|
+
}
|
37
|
+
end
|
38
|
+
when :stimulate
|
39
|
+
ids, stimuls = *cmd
|
40
|
+
|
41
|
+
ids.map! {|id| @entities[id] }
|
42
|
+
|
43
|
+
stimuls.each do |sti|
|
44
|
+
at, weight = *sti
|
45
|
+
weight ||= Infinity
|
46
|
+
ids.each {|entity|
|
47
|
+
entity.stimulate(at, weight, nil)
|
48
|
+
}
|
49
|
+
end
|
50
|
+
when :template
|
51
|
+
ids, base_type, prop_list = *cmd
|
52
|
+
ids.each do |id|
|
53
|
+
raise if templates[id]
|
54
|
+
templates[id] = [base_type, prop_list]
|
55
|
+
end
|
56
|
+
else
|
57
|
+
raise
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
class YinScanner
|
2
|
+
require 'strscan'
|
3
|
+
|
4
|
+
def initialize(str)
|
5
|
+
@s = StringScanner.new(str)
|
6
|
+
@inf = 1.0/0.0
|
7
|
+
end
|
8
|
+
|
9
|
+
def scan
|
10
|
+
while cmd = scan_command()
|
11
|
+
yield cmd
|
12
|
+
end
|
13
|
+
skip_ws()
|
14
|
+
raise "ParseError" unless @s.eos?
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def skip_ws
|
20
|
+
while @s.skip(/(\s+)/) or # skip whitespace
|
21
|
+
@s.skip(/[#](.*)/) # skip comments
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def scan_property
|
26
|
+
pos = @s.pos
|
27
|
+
if name = scan_id()
|
28
|
+
skip_ws()
|
29
|
+
if @s.skip(/=/)
|
30
|
+
value = scan_value()
|
31
|
+
if value != nil
|
32
|
+
return name, value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
@s.pos = pos
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def scan_command
|
42
|
+
skip_ws()
|
43
|
+
type = nil
|
44
|
+
if str = @s.scan(/(TEMPLATE|ENTITY|CONNECT|STIMULATE)\s+/)
|
45
|
+
str.strip!
|
46
|
+
str.downcase!
|
47
|
+
type = str.to_sym
|
48
|
+
end
|
49
|
+
|
50
|
+
ids = scan_idlist()
|
51
|
+
raise "ParseError" if type != nil and ids.empty?
|
52
|
+
return nil if ids.empty?
|
53
|
+
|
54
|
+
scanned_type = scan_type()
|
55
|
+
|
56
|
+
raise "ParseError" if (type and type != scanned_type) or scanned_type.nil?
|
57
|
+
|
58
|
+
case scanned_type
|
59
|
+
when :entity, :template
|
60
|
+
id = scan_id()
|
61
|
+
raise "ParseError" unless id
|
62
|
+
prop_list = scan_propertylist()
|
63
|
+
return scanned_type, ids, id, prop_list
|
64
|
+
when :stimulate
|
65
|
+
stimuls = scan_stimulationlist()
|
66
|
+
raise "ParseError" unless stimuls
|
67
|
+
return scanned_type, ids, stimuls
|
68
|
+
when :connect
|
69
|
+
conns = []
|
70
|
+
conns << ids
|
71
|
+
loop do
|
72
|
+
l = scan_idlist()
|
73
|
+
break if l.empty?
|
74
|
+
conns << l
|
75
|
+
|
76
|
+
skip_ws()
|
77
|
+
break unless @s.skip(/->/)
|
78
|
+
end
|
79
|
+
raise "ParseError" if conns.size < 2
|
80
|
+
return scanned_type, conns
|
81
|
+
else
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def scan_propertylist
|
87
|
+
pos = @s.pos
|
88
|
+
skip_ws()
|
89
|
+
props = {}
|
90
|
+
if @s.skip(/[{]/)
|
91
|
+
loop do
|
92
|
+
name, value = scan_property()
|
93
|
+
break unless name
|
94
|
+
props[name] = value
|
95
|
+
end
|
96
|
+
skip_ws()
|
97
|
+
return props if @s.skip(/[}]/)
|
98
|
+
end
|
99
|
+
|
100
|
+
@s.pos = pos
|
101
|
+
return nil
|
102
|
+
end
|
103
|
+
|
104
|
+
def scan_value
|
105
|
+
skip_ws()
|
106
|
+
if str = @s.scan(/[+-]?[0-9]+([.][0-9]+([eE][+-]?[0-9]+)?)?/)
|
107
|
+
str.to_f
|
108
|
+
elsif @s.skip(/[+]?Inf(inity)?/i)
|
109
|
+
@inf
|
110
|
+
elsif @s.skip(/[-]?Inf(inity)?/i)
|
111
|
+
-@inf
|
112
|
+
elsif @s.skip(/true/)
|
113
|
+
true
|
114
|
+
elsif @s.skip(/false/)
|
115
|
+
false
|
116
|
+
else
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# no skip_ws!
|
122
|
+
def scan_float
|
123
|
+
if str = @s.scan(/[+-]?[0-9]+([.][0-9]+([eE][+-]?[0-9]+)?)?/)
|
124
|
+
str.to_f
|
125
|
+
elsif @s.skip(/[+]?Inf(inity)?/i)
|
126
|
+
@inf
|
127
|
+
elsif @s.skip(/[-]?Inf(inity)?/i)
|
128
|
+
-@inf
|
129
|
+
else
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def scan_stimulationlist
|
135
|
+
pos = @s.pos
|
136
|
+
skip_ws()
|
137
|
+
stimuls = []
|
138
|
+
if @s.skip(/[{]/)
|
139
|
+
loop do
|
140
|
+
arr = scan_stimulation()
|
141
|
+
break unless arr
|
142
|
+
stimuls << arr
|
143
|
+
end
|
144
|
+
skip_ws()
|
145
|
+
return stimuls if @s.skip(/[}]/)
|
146
|
+
end
|
147
|
+
|
148
|
+
@s.pos = pos
|
149
|
+
return nil
|
150
|
+
end
|
151
|
+
|
152
|
+
# [weight@]at
|
153
|
+
# no skip_ws!
|
154
|
+
#
|
155
|
+
def scan_stimulation
|
156
|
+
pos = @s.pos
|
157
|
+
skip_ws()
|
158
|
+
|
159
|
+
if at = scan_float()
|
160
|
+
if @s.skip(/@/)
|
161
|
+
weight = at
|
162
|
+
if at = scan_float()
|
163
|
+
return at, weight
|
164
|
+
end
|
165
|
+
else
|
166
|
+
return at
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
@s.pos = pos
|
171
|
+
return nil
|
172
|
+
end
|
173
|
+
|
174
|
+
def scan_id
|
175
|
+
pos = @s.pos
|
176
|
+
skip_ws()
|
177
|
+
if @s.skip(/["]/)
|
178
|
+
id = @s.scan(/[^"]+/)
|
179
|
+
unless @s.skip(/["]/)
|
180
|
+
@s.pos = pos
|
181
|
+
id = nil
|
182
|
+
end
|
183
|
+
else
|
184
|
+
id = @s.scan(/\w+/)
|
185
|
+
end
|
186
|
+
return id
|
187
|
+
end
|
188
|
+
|
189
|
+
def scan_idlist
|
190
|
+
ids = []
|
191
|
+
loop do
|
192
|
+
id = scan_id()
|
193
|
+
break unless id
|
194
|
+
ids << id
|
195
|
+
skip_ws()
|
196
|
+
break unless @s.skip(/,/) # we expect a "," here
|
197
|
+
end
|
198
|
+
ids
|
199
|
+
end
|
200
|
+
|
201
|
+
def scan_type
|
202
|
+
skip_ws()
|
203
|
+
if @s.skip(/[=]/) then :entity
|
204
|
+
elsif @s.skip(/->/) then :connect
|
205
|
+
elsif @s.skip(/[!]/) then :stimulate
|
206
|
+
elsif @s.skip(/[<]/) then :template
|
207
|
+
else
|
208
|
+
nil
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
if __FILE__ == $0
|
214
|
+
s = YinScanner.new(<<-EOS)
|
215
|
+
#
|
216
|
+
# This is a comment
|
217
|
+
# This also.
|
218
|
+
#
|
219
|
+
# Command names like "TEMPLATE", "ENTITY", "CONNECT" and "STIMULATE"
|
220
|
+
# are optional.
|
221
|
+
#
|
222
|
+
|
223
|
+
TEMPLATE InputType < Neuron_Input {
|
224
|
+
const_threshold = +1.2e+200
|
225
|
+
last_spike_time = -Infinity
|
226
|
+
}
|
227
|
+
|
228
|
+
ENTITY Input1, "input2", Input2, Input3 = InputType
|
229
|
+
ENTITY Input4 = InputType
|
230
|
+
|
231
|
+
Input5, Input6 = Neuron_SRM01 {
|
232
|
+
mem_pot = 10.0
|
233
|
+
}
|
234
|
+
|
235
|
+
Syn1, Syn2, Syn3 = Synapse {
|
236
|
+
weight = 2.3
|
237
|
+
delay = 0.4
|
238
|
+
}
|
239
|
+
|
240
|
+
CONNECT Input1 -> Syn1, Syn2 -> Input5
|
241
|
+
|
242
|
+
STIMULATE Input1, Input5 ! {
|
243
|
+
123@4.4 Inf@23.3 4.5 # weight defaults to Infinity
|
244
|
+
}
|
245
|
+
EOS
|
246
|
+
s.scan {|cmd| p cmd}
|
247
|
+
end
|