yinspire 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,36 @@
|
|
1
|
+
require 'Yinspire/Core/NeuralEntity'
|
2
|
+
require 'Yinspire/Core/Scheduling/Simulator'
|
3
|
+
|
4
|
+
class Simulator
|
5
|
+
|
6
|
+
#
|
7
|
+
# The tolerance (time difference) up to which local stimuli are
|
8
|
+
# accumulated.
|
9
|
+
#
|
10
|
+
property :stimuli_tolerance, 'simtime', :init => Infinity
|
11
|
+
|
12
|
+
#
|
13
|
+
# Statistics counter
|
14
|
+
#
|
15
|
+
property :event_counter, 'uint'
|
16
|
+
property :fire_counter, 'uint'
|
17
|
+
|
18
|
+
stub_method :record_fire, {:at => 'simtime'},{:weight => 'real'},{:source => NeuralEntity}
|
19
|
+
|
20
|
+
#
|
21
|
+
# Overwrite!
|
22
|
+
#
|
23
|
+
def record_fire(at, weight, source)
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :entities
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@entities = Hash.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def run(stop_at=nil)
|
33
|
+
schedule_run(stop_at || Infinity)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'Yinspire/Core/Stimulus'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Module contains code to store local stimuli in a priority queue. Used
|
5
|
+
# by several Neuron models.
|
6
|
+
#
|
7
|
+
module StimuliMixin; cplus2ruby
|
8
|
+
|
9
|
+
#
|
10
|
+
# Each NeuralEntity has it's own local stimuli priority queue.
|
11
|
+
# Neurons make use of this whereas Synapses do not.
|
12
|
+
#
|
13
|
+
# Nevertheless we put this into the base class for simplicity reasons
|
14
|
+
# and as it's quite low overhead (12 bytes).
|
15
|
+
#
|
16
|
+
property :stimuli_pq, 'BinaryHeap<Stimulus, MemoryAllocator<Stimulus> >'
|
17
|
+
|
18
|
+
#
|
19
|
+
# Returns a Ruby array in the form [at1, weight1, at2, weight2]
|
20
|
+
# for +stimuli_pq+.
|
21
|
+
#
|
22
|
+
method :stimuli_pq_to_a, {:returns => Object}, %{
|
23
|
+
VALUE ary = rb_ary_new();
|
24
|
+
@stimuli_pq.each(Stimulus::dump_to_a, &ary);
|
25
|
+
return ary;
|
26
|
+
}
|
27
|
+
|
28
|
+
#
|
29
|
+
# Add a Stimuli to the local priority queue.
|
30
|
+
#
|
31
|
+
method :stimuli_add, {:at => 'simtime'},{:weight => 'real'}, %{
|
32
|
+
Stimulus s; s.at = at; s.weight = weight;
|
33
|
+
|
34
|
+
if (@simulator->stimuli_tolerance >= 0.0)
|
35
|
+
{
|
36
|
+
Stimulus *parent = @stimuli_pq.find_parent(s);
|
37
|
+
|
38
|
+
if (parent != NULL && (s.at - parent->at) <= @simulator->stimuli_tolerance)
|
39
|
+
{
|
40
|
+
parent->weight += s.weight;
|
41
|
+
return;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
@stimuli_pq.push(s);
|
46
|
+
schedule(@stimuli_pq.top().at);
|
47
|
+
}
|
48
|
+
|
49
|
+
#
|
50
|
+
# Consume all Stimuli until +till+ and return the sum of the weights.
|
51
|
+
#
|
52
|
+
method :stimuli_sum, {:till => 'simtime'},{:returns => 'real'}, %{
|
53
|
+
real weight = 0.0;
|
54
|
+
|
55
|
+
while (!@stimuli_pq.empty() && @stimuli_pq.top().at <= till)
|
56
|
+
{
|
57
|
+
weight += @stimuli_pq.top().weight;
|
58
|
+
@stimuli_pq.pop();
|
59
|
+
}
|
60
|
+
|
61
|
+
/*
|
62
|
+
* NOTE: we don't have to remove the entity from the schedule if the
|
63
|
+
* pq is empty.
|
64
|
+
*/
|
65
|
+
if (!@stimuli_pq.empty())
|
66
|
+
{
|
67
|
+
schedule(@stimuli_pq.top().at);
|
68
|
+
}
|
69
|
+
|
70
|
+
return weight;
|
71
|
+
}
|
72
|
+
|
73
|
+
#
|
74
|
+
# Consume all Stimuli until +till+ and return the sum of the weights.
|
75
|
+
# This treats infinitive values specially and instead of summing them,
|
76
|
+
# it sets +is_inf+ to +true+.
|
77
|
+
#
|
78
|
+
method :stimuli_sum_inf, {:till => 'simtime'},{:is_inf => 'bool&'},{:returns => 'real'}, %{
|
79
|
+
real weight = 0.0;
|
80
|
+
is_inf = false;
|
81
|
+
|
82
|
+
while (!@stimuli_pq.empty() && @stimuli_pq.top().at <= till)
|
83
|
+
{
|
84
|
+
if (isinf(@stimuli_pq.top().weight))
|
85
|
+
{
|
86
|
+
is_inf = true;
|
87
|
+
}
|
88
|
+
else
|
89
|
+
{
|
90
|
+
weight += @stimuli_pq.top().weight;
|
91
|
+
}
|
92
|
+
@stimuli_pq.pop();
|
93
|
+
}
|
94
|
+
|
95
|
+
if (!@stimuli_pq.empty())
|
96
|
+
{
|
97
|
+
schedule(@stimuli_pq.top().at);
|
98
|
+
}
|
99
|
+
|
100
|
+
return weight;
|
101
|
+
}
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# The data structure used for storing a fire impluse or any other form
|
3
|
+
# of stimulation.
|
4
|
+
#
|
5
|
+
class Stimulus
|
6
|
+
|
7
|
+
cplus2ruby :no_wrap => true
|
8
|
+
cplus2ruby :order => -1
|
9
|
+
|
10
|
+
property :at, :simtime
|
11
|
+
property :weight, :real
|
12
|
+
|
13
|
+
static_method :less, {:a => 'const Stimulus&'}, {:b => 'const Stimulus&'}, {:returns => 'bool'}, %{
|
14
|
+
return (a.at < b.at);
|
15
|
+
}, :inline => true
|
16
|
+
|
17
|
+
#
|
18
|
+
# Appends +at+ and +weight+ to the Ruby array passed as +ary+.
|
19
|
+
#
|
20
|
+
static_method :dump_to_a, {:s => 'const Stimulus&'},{:ary => 'void*'}, %{
|
21
|
+
rb_ary_push(*((VALUE*)ary), rb_float_new(s.at));
|
22
|
+
rb_ary_push(*((VALUE*)ary), rb_float_new(s.weight));
|
23
|
+
}
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'Yinspire/Core/NeuralEntity'
|
2
|
+
require 'Yinspire/Core/Neuron'
|
3
|
+
|
4
|
+
#
|
5
|
+
# Base class of all Synapses. Defines the structure that is special for
|
6
|
+
# a Synapse, i.e. that a Synapse has a pre and a post-Neuron. Also
|
7
|
+
# each Synapse has a +weight+ and a +delay+.
|
8
|
+
#
|
9
|
+
class Synapse < NeuralEntity
|
10
|
+
|
11
|
+
property :pre_neuron, Neuron
|
12
|
+
property :post_neuron, Neuron
|
13
|
+
|
14
|
+
#
|
15
|
+
# Those pointers are part of an internal linked-list that
|
16
|
+
# starts at a Neuron and connects all pre-synapses of an Neuron
|
17
|
+
# together. In the same way it connects all post-synapses of an
|
18
|
+
# Neuron together.
|
19
|
+
#
|
20
|
+
property :next_pre_synapse, Synapse
|
21
|
+
property :next_post_synapse, Synapse
|
22
|
+
property :prev_pre_synapse, Synapse
|
23
|
+
property :prev_post_synapse, Synapse
|
24
|
+
|
25
|
+
#
|
26
|
+
# The fire weight of a Synapse.
|
27
|
+
#
|
28
|
+
property :weight, 'real', :marshal => true
|
29
|
+
|
30
|
+
#
|
31
|
+
# The propagation delay of a Synapse.
|
32
|
+
#
|
33
|
+
property :delay, 'simtime', :marshal => true
|
34
|
+
|
35
|
+
#
|
36
|
+
# Adding a pre synapse. Target must be a Neuron.
|
37
|
+
#
|
38
|
+
def connect(target)
|
39
|
+
target.add_pre_synapse(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
def disconnect(target)
|
43
|
+
target.delete_pre_synapse(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
def each_connection
|
47
|
+
yield self.post_neuron
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Only propagate the stimulation if it doesn't originate from the
|
52
|
+
# post Neuron. Stimuli from a post Neuron are handled by a specific
|
53
|
+
# Synapse class (e.g. Hebb).
|
54
|
+
#
|
55
|
+
# NOTE: We ignore the weight parameter that is passed by the Neuron.
|
56
|
+
#
|
57
|
+
method :stimulate, {:at => 'simtime'},{:weight => 'real'},{:source => NeuralEntity}, %{
|
58
|
+
if (source != @post_neuron)
|
59
|
+
{
|
60
|
+
@post_neuron->stimulate(at + @delay, @weight, this);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# Common super class of all Dumpers.
|
3
|
+
#
|
4
|
+
class Dumper
|
5
|
+
|
6
|
+
def initialize(simulator)
|
7
|
+
@simulator = simulator
|
8
|
+
@entities = @simulator.entities
|
9
|
+
end
|
10
|
+
|
11
|
+
def dump_entities
|
12
|
+
entities = {}
|
13
|
+
@entities.each {|id, entity|
|
14
|
+
entities[id] = [entity.entity_type || raise, entity.dump]
|
15
|
+
}
|
16
|
+
entities
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'Yinspire/Dumpers/Dumper'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Dumper for the GraphViz[1] dot format.
|
5
|
+
#
|
6
|
+
# Only dumps the net, not the stimulis.
|
7
|
+
#
|
8
|
+
# [1]: http://www.graphviz.org/
|
9
|
+
#
|
10
|
+
class Dumper_Dot < Dumper
|
11
|
+
|
12
|
+
#
|
13
|
+
# NOTE: Unconnected synapses are not shown.
|
14
|
+
#
|
15
|
+
def dump(out)
|
16
|
+
out << "digraph {\n"
|
17
|
+
out << "node [shape = circle];\n"
|
18
|
+
|
19
|
+
@entities.each_value {|entity|
|
20
|
+
next unless entity.kind_of?(Neuron)
|
21
|
+
entity.each_connection do |syn|
|
22
|
+
out << "#{entity.id.inspect} -> #{syn.post_neuron.id.inspect} [label = #{syn.id.inspect} ];\n"
|
23
|
+
end
|
24
|
+
}
|
25
|
+
out << "}\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
class GraphML
|
4
|
+
|
5
|
+
class Graph < Struct.new(:id, :data, :nodes, :edges); end
|
6
|
+
class Node < Struct.new(:id, :data); end
|
7
|
+
class Edge < Struct.new(:id, :data, :source, :target); end
|
8
|
+
|
9
|
+
attr_reader :graphs
|
10
|
+
|
11
|
+
def self.parse(io)
|
12
|
+
doc = REXML::Document.new(io)
|
13
|
+
new().parse(doc)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@keys = Hash.new
|
18
|
+
@graphs = Hash.new
|
19
|
+
@ids = Hash.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse(doc)
|
23
|
+
parse_keys(doc.root)
|
24
|
+
parse_graphs(doc.root)
|
25
|
+
return self
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def check_id(id)
|
31
|
+
raise "duplicate id: #{ id }" if @ids.has_key?(id)
|
32
|
+
@ids[id] = true
|
33
|
+
id
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_keys(root)
|
37
|
+
root.elements.each('key') do |el|
|
38
|
+
id = check_id(el.attributes['id'])
|
39
|
+
(@keys[el.attributes['for']] ||= {})[id] = true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_graphs(root)
|
44
|
+
root.elements.each('graph') do |g|
|
45
|
+
graph = GraphML::Graph.new
|
46
|
+
graph.id = check_id(g.attributes['id'])
|
47
|
+
graph.data = parse_data(g, 'graph')
|
48
|
+
graph.nodes = Hash.new
|
49
|
+
graph.edges = Hash.new
|
50
|
+
@graphs[graph.id] = graph
|
51
|
+
|
52
|
+
g.elements.each('node') do |el|
|
53
|
+
node = GraphML::Node.new
|
54
|
+
node.id = check_id(el.attributes['id'])
|
55
|
+
node.data = parse_data(el, 'node')
|
56
|
+
graph.nodes[node.id] = node
|
57
|
+
end
|
58
|
+
|
59
|
+
g.elements.each('edge') do |el|
|
60
|
+
# FIXME: for now always assume directed edges
|
61
|
+
edge = GraphML::Edge.new
|
62
|
+
edge.id = check_id(el.attributes['id'])
|
63
|
+
edge.source = graph.nodes[el.attributes['source']] || raise
|
64
|
+
edge.target = graph.nodes[el.attributes['target']] || raise
|
65
|
+
edge.data = parse_data(el, 'edge')
|
66
|
+
graph.edges[edge.id] = edge
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse_data(root, for_el)
|
72
|
+
hash = Hash.new
|
73
|
+
root.elements.each('data') do |el|
|
74
|
+
key, value = el.attributes['key'], el.text
|
75
|
+
raise unless @keys[for_el][key]
|
76
|
+
hash[key] = value
|
77
|
+
end
|
78
|
+
hash
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if __FILE__ == $0
|
83
|
+
p GraphML.parse(File.open("../../../examples/nets/skorpion.graphml"))
|
84
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Common super class of all Loaders.
|
3
|
+
#
|
4
|
+
# Uses Cplus2Ruby property annotations to automatically assign
|
5
|
+
# properties:
|
6
|
+
#
|
7
|
+
# property :name, :marshal => true, :init => 123
|
8
|
+
#
|
9
|
+
class Loader
|
10
|
+
|
11
|
+
def initialize(simulator)
|
12
|
+
@simulator = simulator
|
13
|
+
@entities = @simulator.entities
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
#
|
19
|
+
# Create an object with id +id+ of class +entity_type+, where
|
20
|
+
# +entity_type+ is a string.
|
21
|
+
#
|
22
|
+
# Argument +data+ is a hash that contains the property values.
|
23
|
+
#
|
24
|
+
def create_entity(entity_type, id, data)
|
25
|
+
entity = NeuralEntity.new_from_name(entity_type, id, @simulator)
|
26
|
+
entity.load(data)
|
27
|
+
raise if @entities[id]
|
28
|
+
@entities[id] = entity
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#
|
2
|
+
# Load a neuronal net from GraphML format.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2007, 2008 by Michael Neumann (mneumann@ntecs.de)
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'Yinspire/Loaders/Loader'
|
8
|
+
require 'Yinspire/Loaders/GraphML'
|
9
|
+
|
10
|
+
class Loader_GraphML < Loader
|
11
|
+
|
12
|
+
TYPE_MAP = {
|
13
|
+
'NEURONTYPE_KBLIF' => 'Neuron_SRM01',
|
14
|
+
'NEURONTYPE_EKERNEL' => 'Neuron_SRM02',
|
15
|
+
'SYNAPSE_DEFAULT' => 'Synapse',
|
16
|
+
'SYNAPSE_HEBB' => 'Synapse_Hebb'
|
17
|
+
}
|
18
|
+
|
19
|
+
PARAM_MAP = {
|
20
|
+
'absRefPeriod' => ['abs_refr_duration', 'real'],
|
21
|
+
'neuronLFT' => ['last_fire_time', 'real'],
|
22
|
+
'neuronLSET' => ['last_spike_time', 'real'],
|
23
|
+
'neuron_tauM' => ['tau_m', 'real'],
|
24
|
+
'neuron_tauRef' => ['tau_ref', 'real'],
|
25
|
+
'neuron_constThreshold' => ['const_threshold', 'real'],
|
26
|
+
'neuron_refWeight' => ['ref_weight', 'real'],
|
27
|
+
'neuron_arpTime' => ['abs_refr_duration', 'real'],
|
28
|
+
'synapse_weight' => ['weight', 'real'],
|
29
|
+
'synapse_delay' => ['delay', 'real'],
|
30
|
+
'neuronPSP' => ['mem_pot', 'real'],
|
31
|
+
'neuronReset' => ['reset', 'real'],
|
32
|
+
'neuron_tauM' => ['tau_m', 'real'],
|
33
|
+
'neuron_tauRecov' => ['tau_ref', 'real'],
|
34
|
+
'neuron_uReset' => ['u_reset', 'real'],
|
35
|
+
'neuron_threshold' => ['const_threshold', 'real']
|
36
|
+
}
|
37
|
+
|
38
|
+
def load(file)
|
39
|
+
File.open(file) do |f|
|
40
|
+
gml = GraphML.parse(f)
|
41
|
+
g = gml.graphs.values.first
|
42
|
+
default_neuron_type = g.data['graph_default_neuron_type']
|
43
|
+
default_synapse_type = g.data['graph_default_synapse_type']
|
44
|
+
|
45
|
+
#
|
46
|
+
# Create Neurons
|
47
|
+
#
|
48
|
+
g.nodes.each_value {|node|
|
49
|
+
create(node.id, node.data, default_neuron_type, 'neuron_type')
|
50
|
+
}
|
51
|
+
|
52
|
+
#
|
53
|
+
# Create Synapses
|
54
|
+
#
|
55
|
+
g.edges.each_value {|edge|
|
56
|
+
create(edge.id, edge.data, default_synapse_type, 'synapse_type')
|
57
|
+
}
|
58
|
+
|
59
|
+
#
|
60
|
+
# Create Connections between Neurons and Synapses.
|
61
|
+
#
|
62
|
+
g.edges.each_value {|edge|
|
63
|
+
a = @entities[edge.source.id] || raise
|
64
|
+
b = @entities[edge.id] || raise
|
65
|
+
c = @entities[edge.target.id] || raise
|
66
|
+
a.connect(b)
|
67
|
+
b.connect(c)
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
#
|
75
|
+
# Parameter +kind+ is either of "neuron_type" or "synapse_type".
|
76
|
+
#
|
77
|
+
def create(id, data, default_type, kind)
|
78
|
+
entity_type = (TYPE_MAP[data[kind] || default_type] || raise)
|
79
|
+
data.delete(kind)
|
80
|
+
create_entity(entity_type, id, conv_params(data))
|
81
|
+
end
|
82
|
+
|
83
|
+
def conv_params(data)
|
84
|
+
hash = {}
|
85
|
+
data.each {|k,v|
|
86
|
+
name, type = PARAM_MAP[k] || raise
|
87
|
+
case type
|
88
|
+
when 'real'
|
89
|
+
hash[name] = v.strip.to_f
|
90
|
+
else
|
91
|
+
raise
|
92
|
+
end
|
93
|
+
}
|
94
|
+
return hash
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|