Can you see why the code from simulation.cpp marked with:
// clipped output start
and
// clipped output end
produces the clipped output below.(The "..." is where I deleted repeating output to make it more readable)
Letter key can be found below after output.
Initializing neural network...
SOMa memory usage: 155232 Bytes 44 Bytes each
cycle index0 cei0
f1n0c1cycle index0 cei0
f1n1c1cycle index0 cei0
f1n14c1cycle index0 cei0
f1n15c1cycle index0 cei0
f1n28c1cycle index0 cei0
f1n29c1cycle index0 cei0
f1n42c1cycle index0 cei0
f1n43c1cycle index0 cei0
f1n56c1cycle index0 cei0
f1n57c1cycle index0 cei0
f1n70c1cycle index0 cei0
f1n71c1cycle index0 cei0
f1n84c1cycle index0 cei0
f1n85c1cycle index0 cei0
...
f1n3516c1cycle index0 cei0
f1n3517c1cycle index0 cei0
f1n3522c1cycle index0 cei0
f1n3523c1
cei0
i0c0n0e00n1e00n2e00n3e00n4e00n5e00n6e00n7e00n8e00n9e00n10e00n11e00n12e00n13e00n14e00n15e00n16e00n17e00...n3526e00n3527e00
The lines:
f1n0c1cycle index0 cei0
f1n1c1cycle index0 cei0
f1n14c1cycle index0 cei0
f1n15c1cycle index0 cei0
...
should have been
f1n0c1cycle index0 cei0
f1n1c2cycle index0 cei0
f1n14c3cycle index0 cei0
f1n15c4cycle index0 cei0
...
I wanted this last line to read:
i0c840n0e10n1e10n2e00n3e00n4e00n5e00n6e00n7e00n8e00n9e00n10e00n11e00n12e00n13e00n14e10n15e10n16e00...
n - neuron id
f - forcefire
cei - current event index
i - cycle index
c - cycle event count
simulation.cpp
#include <iostream>
#include <sstream>
#include <string>
#include "simulation.h"
#include "connection.h"
#include "config.h"
#include "potentialqueue_local.h"
#include "easy_bmp/EasyBMP.h"
using namespace std;
unsigned int machine_y;
unsigned int machine_x;
unsigned int machines_per_side;
void setup_remote_queues(brain_t *brain_p);
int make_connections(int x, int y, neuron_t *neuron_p, int radius,
short pulse_strength, int conn_index, brain_t *brain_p);
unsigned int get_side_size(const config_t &config)
{
// some locals
unsigned int side_size = config.brain_field_side_size;
// Adjust the side size
machines_per_side = sqrt((double)machine_count);
unsigned int temp_side_size = side_size / machines_per_side;
if(temp_side_size * machines_per_side != side_size) {
if(machine_id == MPI_MASTER) {
cerr << side_size << "(the length of the grid side) "
<< "must be a multiple of " << machines_per_side
<< " (the square root of number of machines)" << endl
<< "Exiting..." << endl;
}
bad_exit();
}
side_size /= machines_per_side;
return side_size;
}
unsigned int get_neuron_count(unsigned int side_size)
{
return side_size * side_size*2;
}
void make_simple_brain(const config_t &config, brain_t &brain)
{
// some locals
unsigned int side_size = brain.side_size;
short threshold = config.neuron_threshold;
unsigned int e_radius = config.e_connection_radius;
unsigned int i_radius = config.i_connection_radius;
// clipped output start
if(config_t::self_p->print_stats_flag && machine_id == MPI_MASTER)
cout << "Initializing neural network..." << endl;
// Determine location of our machine in the machine grid
// (Machine grid is in row major order)
machine_y = machine_id / machines_per_side;
machine_x = machine_id - (machine_y * machines_per_side);
// Set up remote queues
setup_remote_queues(&brain);
#ifdef STATS_ON
if(machine_id == MPI_MASTER)
cout << "SOMa memory usage: " << brain.neuron_count * sizeof(neuron_t) * machine_count
<< " Bytes " << sizeof(neuron_t) << " Bytes each" << endl;
#endif
// Some definitions
potentialqueue_local_t *queue_p = &(brain.loc_potentialqueue);
int global_x_ref = machine_x * side_size;
int global_y_ref = machine_y * side_size;
int id;
int global_x;
int global_y;
int cell_id;
short stride;
short stride_spacing = config.stride_spacing;
short upper_stimuli_stride = config.upper_stimuli_stride * (1+stride_spacing);
short lower_stimuli_stride = config.lower_stimuli_stride * (1+stride_spacing);
// setup neurons (row major order)
if (TESTRUN) {
for(int y = 0; y < side_size; y++)
{
for(int x = 0; x < side_size; x++)
{
id = (y * side_size + x)*2;
brain.neurons[id]
.init(id, machine_id, x, y, E_NEURON, threshold, 0,
config.pulse_duration, config.refractory_period, &brain);
brain.neurons[id+1]
.init(id+1, machine_id, x, y, I_NEURON, threshold, 0,
config.pulse_duration, config.refractory_period, &brain);
}
}
} else {
for(int y = 0; y < side_size; y++)
{
global_y = global_y_ref + y;
for(int x = 0; x < side_size; x++)
{
id = (y * side_size + x)*2;
global_x = global_x_ref + x;
cell_id = (global_y * config.brain_field_side_size + global_x)*2;
if(global_y < config.brain_field_side_size / 2) // upper half
stride = upper_stimuli_stride;
else // lower half
stride = lower_stimuli_stride;
if((cell_id % stride) == 0){
event_t signala(id, 0, 0);
queue_p->push_event(signala, 0);
}
if(((cell_id+1-stride_spacing) % stride) == 0) {
event_t signalb(id+1, 0, 0);
queue_p->push_event(signalb, 0);
}
brain.neurons[id].init(id, machine_id, x, y, E_NEURON, threshold,
0, config.pulse_duration, config.refractory_period, &brain);
brain.neurons[id+1].init(id+1, machine_id, x, y, I_NEURON, threshold,
0, config.pulse_duration, config.refractory_period, &brain);
}
}
}
queue_p->show();
// clipped output end
cout << endl << "after neuron init" << endl;
// Create connections
unsigned int e_conn_count =
brain.neuron_count * ((e_radius * 2 + 1) * (e_radius * 2 + 1) - 1);
unsigned int i_conn_count =
brain.neuron_count * ((i_radius * 2 + 1) * (i_radius * 2 + 1) - 1);
#ifdef STATS_ON
if(machine_id == MPI_MASTER)
cout << "SYnapse memory usage: " << (e_conn_count + i_conn_count) * machine_count *
sizeof(connection_t) << " Bytes " << sizeof(connection_t) << " Bytes each" << endl << endl;
#endif
brain.connections = new connection_t[e_conn_count + i_conn_count];
queue_p->show();
cout << endl << "after connections" << endl;
// Go through each neuron
int conn_index = 0;
neuron_t *self_p;
for(int y = 0; y < side_size; y++) {
for(int x = 0; x < side_size; x++) {
// Find our neuron
id = (y * side_size + x)*2;
self_p = &(brain.neurons[id]);
conn_index = make_connections(x, y, self_p, e_radius,
config.e_pulse_strength, conn_index, &brain);
self_p = &(brain.neurons[id+1]);
conn_index = make_connections(x, y, self_p, i_radius,
config.i_pulse_strength, conn_index, &brain);
}
}
if(config_t::self_p->print_stats_flag && machine_id == MPI_MASTER) {
queue_p->show();
cout << "Finished initialization" << endl;
}
}
void setup_remote_queues(brain_t *brain_p)
{
if(machine_count > 1)
{
unsigned int queue_size = brain_p->loc_potentialqueue.queue_size;
int left_machine, up_machine, right_machine, down_machine;
// left
if(machine_x > 0)
left_machine = machine_x - 1;
else
left_machine = machines_per_side - 1;
brain_p->remotequeues_p[LEFT] =
new eventqueue_remote_t(queue_size, machine_y * machines_per_side + left_machine);
// up
if(machine_y > 0)
up_machine = (machine_y - 1) * machines_per_side;
else
up_machine = (machines_per_side - 1) * machines_per_side;
brain_p->remotequeues_p[UP] =
new eventqueue_remote_t(queue_size, up_machine + machine_x);
// right
if(machine_x < (machines_per_side - 1))
right_machine = machine_x + 1;
else
right_machine = 0;
brain_p->remotequeues_p[RIGHT] =
new eventqueue_remote_t(queue_size, machine_y * machines_per_side + right_machine);
// down
if(machine_y < (machines_per_side - 1))
down_machine = (machine_y + 1) * machines_per_side;
else
down_machine = 0 * machines_per_side;
brain_p->remotequeues_p[DOWN] =
new eventqueue_remote_t(queue_size, down_machine + machine_x);
// leftup
brain_p->remotequeues_p[LEFTUP] =
new eventqueue_remote_t(queue_size, up_machine + left_machine);
// leftdown
brain_p->remotequeues_p[LEFTDOWN] =
new eventqueue_remote_t(queue_size, down_machine + left_machine);
// rightup
brain_p->remotequeues_p[RIGHTUP] =
new eventqueue_remote_t(queue_size, up_machine + right_machine);
// rightdown
brain_p->remotequeues_p[RIGHTDOWN] =
new eventqueue_remote_t(queue_size, down_machine + right_machine);
}
}
int make_connections(int x, int y, neuron_t *neuron_p, int radius,
short pulse_strength, int conn_index, brain_t *brain_p)
{
// Set up some locals
event_storage_t *queue_p = NULL;
int side_size = brain_p->side_size;
int i = 0;
int neighbor_neuron;
int x_abs;
int x_rel;
int y_abs;
int y_rel;
int id_y_offset;
connection_t *connection_p;
// Create connections in the radius
for (y_rel = -radius; y_rel <= radius; y_rel++) {
y_abs = y + y_rel;
id_y_offset = ((y_abs + side_size) % side_size) * side_size*2;
for (x_rel = -radius; x_rel <= radius; x_rel++) {
if(x_rel != 0 || y_rel != 0) {
x_abs = x + x_rel;
if ((machine_count == 1) ||
(x_abs >= 0 && x_abs < side_size && y_abs >= 0 && y_abs < side_size))
queue_p = &(brain_p->loc_potentialqueue);
else {
if (y_abs < 0)
queue_p = brain_p->remotequeues_p[UP];
else if(y_abs >= side_size)
queue_p = brain_p->remotequeues_p[DOWN];
if (x_abs < 0) {
queue_p = brain_p->remotequeues_p[LEFT];
if(y_abs < 0)
queue_p = brain_p->remotequeues_p[LEFTUP];
else if(y_abs >= side_size)
queue_p = brain_p->remotequeues_p[LEFTDOWN];
} else if(x_abs >= side_size) {
queue_p = brain_p->remotequeues_p[RIGHT];
if(y_abs < 0)
queue_p = brain_p->remotequeues_p[RIGHTUP];
else if(y_abs >= side_size)
queue_p = brain_p->remotequeues_p[RIGHTDOWN];
}
}
x_abs = (x_abs + side_size) % side_size;
neighbor_neuron= id_y_offset + x_abs*2;
connection_p = &(brain_p->connections[conn_index + i++]);
connection_p->init(max(abs(x_rel), abs(y_rel)), neighbor_neuron, pulse_strength, queue_p);
connection_p = &(brain_p->connections[conn_index + i++]);
connection_p->init(max(abs(x_rel), abs(y_rel)), neighbor_neuron+1, pulse_strength, queue_p);
}
}
}
neuron_p->connections = &(brain_p->connections[conn_index]);
neuron_p->connection_count = i;
return conn_index + i;
}
void output_frame(long frame, const brain_t *brain_p, unsigned int side)
{
frame--;
BMP out;
out.SetSize(side, side);
out.SetBitDepth(24);
// Set colors...
neuron_t *neuron_p;
unsigned int neuron_id;
float potential;
float threshold;
float color;
int x;
int y;
/* posible problem with the following code:
if there is only one neuron per x,y coordinate one color (red or blue)
would not be set. In that case you would need to init colors to 0. */
if(config_t::self_p->output_images_flag == 1) {
for(neuron_id = 0; neuron_id < brain_p->neuron_count; neuron_id++) {
neuron_p = &(brain_p->neurons[neuron_id]);
potential = max(0, (int)neuron_p->get_potential());
threshold = neuron_p->get_threshold();
color = min((int)potential, (int)threshold) / threshold * 255.0f;
x = neuron_p->get_x();
y = neuron_p->get_y();
if (neuron_p->neuron_type == E_NEURON)
out(x, y)->Red = color;
else
out(x, y)->Blue = color;
out(x, y)->Green = 0;
// reset neuron
neuron_p->must_or_just_fired = false;
}
} else {
for(neuron_id = 0; neuron_id < brain_p->neuron_count; neuron_id++) {
neuron_p = &(brain_p->neurons[neuron_id]);
x = neuron_p->get_x();
y = neuron_p->get_y();
if(neuron_p->must_or_just_fired) {
color = 255;
neuron_p->must_or_just_fired = false; // reset neuron
} else
color = 0;
if (neuron_p->neuron_type == E_NEURON)
out(x, y)->Red = color;
else
out(x, y)->Blue = color;
out(x, y)->Green = 0;
}
}
ostringstream oss, xss, yss;
oss << frame;
xss << machine_x;
yss << machine_y;
string dir(config_t::self_p->output_dir);
dir = dir + "/" + oss.str() + "_" + xss.str() + "_" + yss.str() + ".bmp";
out.WriteToFile(dir.c_str());
}
potentialqueue_local.h
#ifndef _POTENTIALQUEUE_LOCAL_H_
#define _POTENTIALQUEUE_LOCAL_H_
#include <vector>
#include "event_storage.h"
#include "neuron.h"
#include "eventqueue_remote.h"
// stores a potential sum for a neuron for a cycle
class combine_event_t
{
public:
combine_event_t();
void add_potential(short _potential);
short pop_potential();
void set_forcefire();
bool pop_forcefire();
void show();
private:
short potential;
bool forcefire;
};
class cycle_data_t
{
protected:
typedef std::vector<combine_event_t> combine_events_t;
public:
cycle_data_t();
cycle_data_t(unsigned int size);
~cycle_data_t();
void show();
public:
combine_events_t combine_events;
unsigned int event_count;
};
class potentialqueue_local_t : public event_storage_t
{
protected:
typedef std::vector<cycle_data_t> potentials_t;
public:
potentialqueue_local_t();
potentialqueue_local_t(unsigned int size, unsigned int neuron_count);
virtual ~potentialqueue_local_t();
void push_event(const event_t &signal, unsigned int delay);
void execute_moment(unsigned long step, eventqueue_remote_t *remotequeues_p[8]);
unsigned int get_capacity();
void show();
protected:
potentials_t potential_queue;
public:
neuron_t *neurons; // array of neurons
};
#endif // _POTENTIALQUEUE_LOCAL_H_
potentialqueue_local.cpp
#include <iostream>
#include "config.h"
#include "potentialqueue_local.h"
using namespace std;
combine_event_t::combine_event_t()
{
potential = 0;
forcefire = false;
cout << "f" << 0;
}
void combine_event_t::add_potential(short _potential)
{
potential += _potential;
}
void combine_event_t::set_forcefire()
{
forcefire = true;
cout << "f" << forcefire;
}
bool combine_event_t::pop_forcefire()
{
bool current_forcefire = forcefire;
forcefire = false;
cout << "f" << 0;
return current_forcefire;
}
short combine_event_t::pop_potential()
{
short current_potential = potential;
potential = 0;
return current_potential;
}
void combine_event_t::show()
{
cout << "e" << forcefire << potential;
}
cycle_data_t::cycle_data_t()
{
}
cycle_data_t::cycle_data_t(unsigned int neuron_count) : combine_events(neuron_count)
{
int id = 0;
for(;id < neuron_count; id++) {
combine_events[id] = combine_event_t();
}
event_count = 0;
}
cycle_data_t::~cycle_data_t()
{
}
void cycle_data_t::show()
{
cout << "c" << event_count;
int id = 0;
for(;id < combine_events.size(); id++) {
cout << "n" << id;
combine_events[id].show();
}
}
potentialqueue_local_t::potentialqueue_local_t()
{
}
potentialqueue_local_t::potentialqueue_local_t(unsigned int size, unsigned int neuron_count)
: event_storage_t(size), potential_queue(size, cycle_data_t(neuron_count))
{
// Initialize the queue
/* int i;
for(i = 0; i < size; i++) {
potential_queue[i] = cycle_data_t(neuron_count);
}*/
}
potentialqueue_local_t::~potentialqueue_local_t()
{
}
void potentialqueue_local_t::push_event(const event_t &signal, unsigned int delay)
{
int cycle_index = (current_event_index + delay) % queue_size;
cout << "cycle index" << cycle_index << " cei" << current_event_index << endl;
cycle_data_t event_cycle = potential_queue[cycle_index];
if (signal.potential == 0) {
event_cycle.combine_events[signal.dest_neuron].set_forcefire();
event_cycle.event_count++;
future_events_count++;
cout << "n" << signal.dest_neuron << "c" << event_cycle.event_count;
}else {
event_cycle.combine_events[signal.dest_neuron].add_potential(signal.potential);
cycle_index = (cycle_index + signal.duration) % queue_size;
event_cycle = potential_queue[cycle_index];
event_cycle.combine_events[signal.dest_neuron].add_potential(-signal.potential);
event_cycle.event_count += 2;
future_events_count += 2;
}
}
void potentialqueue_local_t::execute_moment(unsigned long step, eventqueue_remote_t *remotequeues_p[8])
{
// Grab the moment
cycle_data_t event_cycle = potential_queue[current_event_index];
// Execute the moment
unsigned int neuron_id = 0;
unsigned int neuron_count = event_cycle.combine_events.size();
for(; neuron_id < neuron_count; neuron_id++) {
if(event_cycle.combine_events[neuron_id].pop_forcefire()) {
// Force neuron to fire
neurons[neuron_id].force_fire(this, remotequeues_p);
cout << "1";
} else {
// Add potential to subject neurons
neurons[neuron_id].add_potential(event_cycle.combine_events[neuron_id].pop_potential());
cout << "0";
}
}
cout << " " << current_event_index << endl;
current_events_count = event_cycle.event_count;
event_cycle.event_count = 0;
#ifdef STATS_ON
future_events_count -= current_events_count;
#endif
if(config_t::self_p->print_stats_flag)
std::cout << "Machine " << machine_id << ", step " << step + 1
<< ": performed " << current_events_count << " events" << std::endl;
}
unsigned int potentialqueue_local_t::get_capacity()
{
int capacity = 0;
int cycle_index;
for(cycle_index = 0; cycle_index < queue_size; cycle_index++) {
capacity += potential_queue[cycle_index].combine_events.capacity();
}
return capacity;
}
void potentialqueue_local_t::show()
{
cout << endl << "cei" << current_event_index << endl;
int cycle_index;
for(cycle_index = 0; cycle_index < queue_size; cycle_index++) {
cout << "i" << cycle_index;
potential_queue[cycle_index].show();
cout << endl << endl;
}
}
event_storage.h
#ifndef _EVENT_STORAGE_H_
#define _EVENT_STORAGE_H_
// An event
class event_t
{
public:
event_t();
event_t(int _dest_neuron, short _potential, short _duration);
public:
int dest_neuron;
short potential;
short duration; // values < 0 induce a the dest_neuron to force fire
};
class event_storage_t
{
public:
event_storage_t();
event_storage_t(unsigned int size);
virtual ~event_storage_t();
// Pushing events on the queue
virtual void push_event(const event_t &signal, unsigned int delay) = 0;
virtual unsigned int get_capacity() = 0;
void update_moment();
unsigned int get_future_events_count();
unsigned int get_current_events_count();
unsigned int queue_size;
protected:
unsigned int current_event_index;
unsigned int current_events_count;
unsigned int future_events_count;
};
#endif // _EVENT_STORAGE_H_
event_storage.cpp
#include <iostream>
#include "event_storage.h"
event_t::event_t()
{
}
event_t::event_t(int _dest_neuron, short _potential, short _duration)
: dest_neuron(_dest_neuron), potential(_potential), duration(_duration)
{
}
event_storage_t::event_storage_t()
{
}
event_storage_t::event_storage_t(unsigned int size)
{
queue_size = size;
current_event_index = 0;
current_events_count = 0;
future_events_count = 0;
}
event_storage_t::~event_storage_t()
{
}
void event_storage_t::update_moment()
{
current_event_index = (current_event_index + 1) % queue_size;
}
unsigned int event_storage_t::get_future_events_count()
{
return future_events_count;
}
unsigned int event_storage_t::get_current_events_count()
{
return current_events_count;
}