Auryn simulator  v0.8.1-206-gb56e451
Plastic Spiking Neural Network Simulator
SimpleMatrix.h
Go to the documentation of this file.
1 /*
2 * Copyright 2014-2018 Friedemann Zenke
3 *
4 * This file is part of Auryn, a simulation package for plastic
5 * spiking neural networks.
6 *
7 * Auryn is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Auryn is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Auryn. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * If you are using Auryn or parts of it for your work please cite:
21 * Zenke, F. and Gerstner, W., 2014. Limits to high-speed simulations
22 * of spiking neural networks using general-purpose computers.
23 * Front Neuroinform 8, 76. doi: 10.3389/fninf.2014.00076
24 */
25 
26 #ifndef SIMPLEMATRIX_H_
27 #define SIMPLEMATRIX_H_
28 
29 #include "auryn_global.h"
30 #include <string.h>
31 
32 #include <boost/serialization/utility.hpp>
33 #include <boost/serialization/split_member.hpp>
34 
35 namespace auryn {
36 
42 template <typename T>
44 {
45 private:
47  template<class Archive>
48  void save(Archive & ar, const unsigned int version) const
49  {
50  ar & m_rows;
51  ar & n_cols;
52  ar & datasize;
53  ar & n_nonzero;
54  for (NeuronID i = 0 ; i < m_rows ; ++i) {
55  for (NeuronID * r = rowptrs[i] ; r < rowptrs[i+1] ; ++r ) {
56  ar & i;
57  ar & *r;
58  ar & coldata[r-colinds];
59  }
60  }
61  }
62  template<class Archive>
63  void load(Archive & ar, const unsigned int version)
64  {
65  AurynLong load_datasize;
66  AurynLong nnz;
67 
68  ar & m_rows;
69  ar & n_cols;
70  ar & load_datasize;
71  ar & nnz;
72 
73  resize_buffer_and_clear(load_datasize);
74 
75  for (AurynLong c = 0 ; c < nnz ; ++c) {
76  NeuronID i,j;
77  T val;
78  ar & i;
79  ar & j;
80  ar & val;
81  push_back(i,j,val);
82  }
83  }
84  BOOST_SERIALIZATION_SPLIT_MEMBER()
85 
86 
87  NeuronID m_rows,n_cols;
89  NeuronID current_row,current_col;
91  AurynLong n_nonzero;
93  AurynLong datasize;
94 protected:
100  T * coldata;
101 
103  void init(NeuronID m, NeuronID n, AurynLong size=256);
104  void free();
105 
106 public:
107  SimpleMatrix();
108  SimpleMatrix(SimpleMatrix * mat);
109  SimpleMatrix(NeuronID rows, NeuronID cols);
110  SimpleMatrix(NeuronID rows, NeuronID cols, AurynLong size);
111  virtual ~SimpleMatrix();
112 
113  void clear();
114 
118  void resize_buffer(AurynLong newsize);
119 
123 
127  void prune();
128 
134  void push_back(const NeuronID i, const NeuronID j, const T value);
135  void copy(SimpleMatrix * mat);
136  void set_data(AurynLong i, T value);
137  void scale_data(AurynLong i, T value);
139  T * get_data_ptr(const AurynLong i);
141  T get_data(const AurynLong i);
143  T * get_data_ptr(const NeuronID * ind_ptr);
145  T get_data(const NeuronID * ind_ptr);
150  void fill_zeros();
155  void fill_na();
157  T get(NeuronID i, NeuronID j);
158  bool exists(NeuronID i, NeuronID j);
160  T * get_ptr(NeuronID i, NeuronID j);
163  T * get_ptr(AurynLong data_index);
164  T get_value(AurynLong data_index);
165  void add_value(AurynLong data_index, T value);
166  NeuronID get_colind(AurynLong data_index);
167  bool set(NeuronID i, NeuronID j, T value);
169  void set_all(T value);
171  void set_row(NeuronID i, T value);
173  void scale_row(NeuronID i, T value);
175  void scale_all(T value);
177  void set_col(NeuronID j, T value);
179  void scale_col(NeuronID j, T value);
180  double sum_col(NeuronID j);
183  void print();
184  double mean();
192  NeuronID ** get_rowptrs();
193  T * get_data_begin();
195  T * get_data_end();
197  T get_value(NeuronID i);
199  T get_value(NeuronID * r);
201  T * get_value_ptr(NeuronID i);
203  T * get_value_ptr(NeuronID * r);
205 };
206 
207 template <typename T>
208 T * SimpleMatrix<T>::get_data_ptr(AurynLong i)
209 {
210  return coldata+i;
211 }
212 
213 template <typename T>
215 {
216  return coldata[i];
217 }
218 
219 template <typename T>
221 {
222  size_t ptr_offset = ind_ptr-get_ind_begin();
223  return coldata+ptr_offset;
224 }
225 
226 template <typename T>
228 {
229  return *(get_data_ptr(ind_ptr));
230 }
231 
232 template <typename T>
234 {
235  if (i<datasize)
236  coldata[i] = value;
237 }
238 
239 template <typename T>
241 {
242  if (i<datasize)
243  coldata[i] *= value;
244 }
245 
246 
247 template <typename T>
249 {
250  current_row = 0;
251  current_col = 0;
252  n_nonzero = 0;
253  rowptrs[0] = colinds;
254  rowptrs[1] = colinds;
255 }
256 
257 template <typename T>
259 {
260  m_rows = m;
261  n_cols = n;
262  datasize = size;
263  rowptrs = new NeuronID * [m_rows+1];
264  colinds = new NeuronID [datasize];
265  coldata = new T [datasize];
266  clear();
267 }
268 
269 template <typename T>
271 {
272  const AurynLong oldsize = datasize;
273  if ( oldsize == newsize ) return;
274  const AurynLong copysize = std::min(oldsize,newsize);
275 
276  // std::cout << " copy colinds " << std::endl;
277 
278  NeuronID * new_colinds = new NeuronID [newsize];
279  std::copy(colinds, colinds+copysize, new_colinds);
280 
281  // std::cout << " update rowptrs " << std::endl;
282 
283  // update rowpointers
284  ptrdiff_t offset = new_colinds-colinds;
285  for ( NeuronID i = 0 ; i < m_rows+1 ; ++i ) {
286  rowptrs[i] += offset;
287  }
288 
289  // std::cout << " delete old colinds " << std::endl;
290  // FIXME I get regular crashes in this line:
291  // invalid pointer: 0x0000000001d954c0 ***
292  delete [] colinds;
293 
294  // std::cout << " replace colinds " << std::endl;
295  colinds = new_colinds;
296 
297  // std::cout << " create new data array " << std::endl;
298  T * new_coldata = new T [newsize];
299  std::copy(coldata, coldata+copysize, new_coldata);
300  delete [] coldata;
301  coldata = new_coldata;
302 
303  datasize = newsize;
304  // std::cout << " done " << std::endl;
305 }
306 
307 template <typename T>
309 {
310  // free();
311  // init(m_rows, n_cols, size);
312  resize_buffer(size);
313  clear();
314 }
315 
316 template <typename T>
318 {
319  if ( get_datasize() > get_nonzero() )
321 }
322 
323 template <typename T>
325 {
326  init(1,1);
327 }
328 
329 template <typename T>
331 {
332  init(mat->get_m_rows(),mat->get_n_cols(),mat->get_nonzero());
333  copy(mat);
334 }
335 
336 
337 
338 template <typename T>
340 {
341  init(rows,cols);
342 }
343 
344 template <typename T>
346 {
347  init(rows,cols,datasize);
348 }
349 
350 template <typename T>
352 {
353  delete [] rowptrs;
354  delete [] colinds;
355  delete [] coldata;
356 }
357 
358 template <typename T>
360 {
361  if ( get_m_rows() != mat->get_m_rows() || get_n_cols() != mat->get_n_cols() )
363 
364  clear();
365 
366  for ( NeuronID i = 0 ; i < mat->get_m_rows() ; ++i ) {
367  for ( NeuronID * r = mat->get_row_begin(i) ; r != mat->get_row_end(i) ; ++r ) {
368  push_back(i,*r,mat->get_value(r));
369  }
370  }
371 }
372 
373 template <typename T>
375 {
376  free();
377 }
378 
379 template <typename T>
381 {
382  if ( i >= m_rows || j >= n_cols ) throw AurynMatrixDimensionalityException();
383  while ( i > current_row )
384  {
385  rowptrs[current_row+2] = rowptrs[current_row+1]; // save value of last element
386  current_col = 0;
387  current_row++;
388  }
389  current_col = j;
390  if (i >= current_row && j >= current_col) {
391  if ( n_nonzero >= datasize ) throw AurynMatrixBufferException();
392  *(rowptrs[i+1]) = j; // write last j to end of index array
393  coldata[rowptrs[i+1]-colinds] = value; // write value to end of data array
394  ++rowptrs[i+1]; //increment end by one
395  rowptrs[m_rows] = rowptrs[i+1]; // last (m_row+1) marks end of last row
396  n_nonzero++;
397  } else {
399  }
400 }
401 
402 template <typename T>
404 {
405  return datasize;
406 }
407 
408 
409 template <typename T>
411 {
412  return n_nonzero;
413 }
414 
415 template <typename T>
417 {
418  for ( NeuronID i = current_row ; i < m_rows-1 ; ++i )
419  {
420  rowptrs[i+2] = rowptrs[i+1]; // save value of last element
421  }
422  current_row = get_m_rows();
423 }
424 
425 template <typename T>
427 {
428  fill_na();
429 }
430 
431 template <typename T>
433 {
434  return *get_ptr(i,j);
435 }
436 
437 template <typename T>
439 {
440  if ( get_ptr(i,j) == NULL )
441  return false;
442  else
443  return true;
444 }
445 
446 template <typename T>
448 {
449  // check bounds
450  if ( !(i < m_rows && j < n_cols) ) return NULL;
451 
452 #ifdef DEBUG
453  std::cout << "enter search" << std::endl;
454 #endif // DEBUG
455  // perform binary search
456  NeuronID * lo = rowptrs[i];
457  NeuronID * hi = rowptrs[i+1];
458 
459  if ( lo >= hi ) // no elements/targets in this row
460  return NULL;
461 
462  while ( lo < hi ) {
463  NeuronID * c = lo + (hi-lo)/2;
464  if ( *c < j ) lo = c+1;
465  else hi = c;
466 #ifdef DEBUG
467  std::cout << i << ":" << j << " " << *lo << ":" << *hi << std::endl;
468 #endif // DEBUG
469  }
470 
471  if ( *lo == j ) {
472  return coldata+(lo-colinds);
473  }
474 
475  return NULL;
476 }
477 
478 template <typename T>
480 {
481  return &coldata[data_index];
482 }
483 
484 template <typename T>
486 {
487  return coldata[data_index];
488 }
489 
490 template <typename T>
491 void SimpleMatrix<T>::add_value(AurynLong data_index, T value)
492 {
493  coldata[data_index] += value;
494 }
495 
496 template <typename T>
498 {
499  return colinds[data_index];
500 }
501 
502 template <typename T>
504 {
505  T * ptr = get_ptr(i,j);
506  if ( ptr != NULL) {
507  *ptr = value;
508  return true;
509  }
510  else
511  return false;
512 }
513 
514 template <typename T>
516 {
517  NeuronID * rowbegin = rowptrs[i];
518  NeuronID * rowend = rowptrs[i+1]--;
519 
520  for (NeuronID * c = rowbegin ; c <= rowend ; ++c)
521  {
522  coldata[c-colinds] *= value;
523  }
524 }
525 
526 template <typename T>
528 {
529  for ( AurynLong i = 0 ; i < n_nonzero ; ++i )
530  scale_data( i , value );
531 }
532 
533 template <typename T>
535 {
536  NeuronID * rowbegin = rowptrs[i];
537  NeuronID * rowend = rowptrs[i+1]--;
538 
539  for (NeuronID * c = rowbegin ; c <= rowend ; ++c)
540  {
541  coldata[c-colinds] = value;
542  }
543 }
544 
545 template <typename T>
547 {
548  for ( AurynLong i = 0 ; i < n_nonzero ; ++i )
549  set_data( i , value );
550 }
551 
552 template <typename T>
554 {
555  for ( AurynLong i = 0 ; i < n_nonzero ; ++i ) {
556  if ( colinds[i] == j ) scale_data(i,value);
557  }
558 }
559 
560 template <typename T>
562 {
563  double sum = 0;
564  for ( AurynLong i = 0 ; i < n_nonzero ; ++i ) {
565  if ( colinds[i] == j )
566  sum += *(get_data_begin()+i);
567  }
568  return sum;
569 }
570 
571 template <typename T>
573 {
574  for ( AurynLong i = 0 ; i < n_nonzero ; ++i ) {
575  if ( colinds[i] == j ) set_data(i,value);
576  }
577 }
578 
579 template <typename T>
581 {
582  return rowptrs[0];
583 }
584 
585 template <typename T>
587 {
588  return rowptrs[i];
589 }
590 
591 template <typename T>
593 {
594  return rowptrs[i]-rowptrs[0];
595 }
596 
597 template <typename T>
599 {
600  return rowptrs[i+1];
601 }
602 
603 template <typename T>
605 {
606  return rowptrs[i+1]-rowptrs[0];
607 }
608 
609 
610 template <typename T>
612 {
613  return rowptrs;
614 }
615 
616 template <typename T>
618 {
619  return coldata;
620 }
621 
622 template <typename T>
624 {
625  return coldata+get_nonzero();
626 }
627 
628 
629 template <typename T>
631 {
632  return 1.*n_nonzero/datasize;
633 }
634 
635 template <typename T>
637 {
638  return m_rows;
639 }
640 
641 template <typename T>
643 {
644  return n_cols;
645 }
646 
647 template <typename T>
649 {
650  for (NeuronID i = 0 ; i < m_rows ; ++i) {
651  for (NeuronID * r = get_row_begin(i) ; r != get_row_end(i) ; ++r ) {
652  std::cout << i << " " << *r << " " << coldata[r-colinds] << "\n";
653  }
654  }
655 }
656 
657 template <typename T>
659 {
660  double sum = 0;
661  for (NeuronID i = 0 ; i < get_nonzero() ; ++i) {
662  sum += coldata[i];
663  }
664  return sum/get_nonzero();
665 }
666 
667 template <typename T>
669 {
670  return get_data_begin()[i];
671 }
672 
673 template <typename T>
675 {
676  return get_data_begin()[r-get_ind_begin()];
677 }
678 
679 template <typename T>
681 {
682  return &get_data_begin()[i];
683 }
684 
685 template <typename T>
687 {
688  return &get_data_begin()[r-get_ind_begin()];
689 }
690 
691 template <typename T>
693 {
694  return r-get_ind_begin();
695 }
696 
697 }
698 
699 
700 #endif /*SIMPLEMATRIX_H_*/
701 
r
Definition: mkpat.py:9
void add_value(AurynLong data_index, T value)
Definition: SimpleMatrix.h:491
T * coldata
Definition: SimpleMatrix.h:100
SimpleMatrix()
Definition: SimpleMatrix.h:324
void prune()
Definition: SimpleMatrix.h:317
friend class boost::serialization::access
Definition: SimpleMatrix.h:46
AurynLong get_row_begin_index(NeuronID i)
Definition: SimpleMatrix.h:592
void set_all(T value)
Definition: SimpleMatrix.h:546
Template for a sparse matrix with row major ordering and fast access of rows.
Definition: SimpleMatrix.h:43
virtual ~SimpleMatrix()
Definition: SimpleMatrix.h:374
double AurynDouble
Higher precision floating point datatype.
Definition: auryn_definitions.h:158
void copy(SimpleMatrix *mat)
Definition: SimpleMatrix.h:359
void clear()
Definition: SimpleMatrix.h:248
int n
Definition: mkpat.py:5
void free()
Definition: SimpleMatrix.h:351
NeuronID * get_row_end(NeuronID i)
Definition: SimpleMatrix.h:598
NeuronID ** rowptrs
Definition: SimpleMatrix.h:96
AurynDouble get_fill_level()
Definition: SimpleMatrix.h:630
void push_back(const NeuronID i, const NeuronID j, const T value)
Definition: SimpleMatrix.h:380
AurynLong get_row_end_index(NeuronID i)
Definition: SimpleMatrix.h:604
Definition: ABSConnection.h:38
void set_data(AurynLong i, T value)
Definition: SimpleMatrix.h:233
unsigned long AurynLong
An unsigned long type used to count synapses or similar.
Definition: auryn_definitions.h:154
T get_data(const AurynLong i)
Definition: SimpleMatrix.h:214
T get_value(AurynLong data_index)
Definition: SimpleMatrix.h:485
void scale_col(NeuronID j, T value)
Definition: SimpleMatrix.h:553
NeuronID get_m_rows()
Definition: SimpleMatrix.h:636
NeuronID ** get_rowptrs()
Definition: SimpleMatrix.h:611
bool exists(NeuronID i, NeuronID j)
Definition: SimpleMatrix.h:438
bool set(NeuronID i, NeuronID j, T value)
Definition: SimpleMatrix.h:503
double mean()
Definition: SimpleMatrix.h:658
Definition: auryn_definitions.h:240
T * get_data_ptr(const AurynLong i)
Definition: SimpleMatrix.h:208
NeuronID get_n_cols()
Definition: SimpleMatrix.h:642
void set_row(NeuronID i, T value)
Definition: SimpleMatrix.h:534
T get(NeuronID i, NeuronID j)
Definition: SimpleMatrix.h:432
void resize_buffer_and_clear(AurynLong size)
Definition: SimpleMatrix.h:308
NeuronID * colinds
Definition: SimpleMatrix.h:98
void fill_zeros()
Same as fill_na.
Definition: SimpleMatrix.h:426
double sum_col(NeuronID j)
Definition: SimpleMatrix.h:561
NeuronID get_data_offset(NeuronID *r)
Definition: SimpleMatrix.h:692
void scale_all(T value)
Definition: SimpleMatrix.h:527
void set_col(NeuronID j, T value)
Definition: SimpleMatrix.h:572
AurynLong get_nonzero()
Definition: SimpleMatrix.h:410
void init(NeuronID m, NeuronID n, AurynLong size=256)
Definition: SimpleMatrix.h:258
Definition: auryn_definitions.h:224
T * get_data_begin()
Definition: SimpleMatrix.h:617
AurynLong get_datasize()
Definition: SimpleMatrix.h:403
void scale_data(AurynLong i, T value)
Definition: SimpleMatrix.h:240
void fill_na()
Marks the remainder of buffers non-existing connections.
Definition: SimpleMatrix.h:416
T * get_data_end()
Returns value behind last element in data array corresponding to a nonzero value. ...
Definition: SimpleMatrix.h:623
Definition: auryn_definitions.h:248
NeuronID get_colind(AurynLong data_index)
Definition: SimpleMatrix.h:497
NeuronID * get_ind_begin()
Definition: SimpleMatrix.h:580
void scale_row(NeuronID i, T value)
Definition: SimpleMatrix.h:515
T * get_ptr(NeuronID i, NeuronID j)
Definition: SimpleMatrix.h:447
void resize_buffer(AurynLong newsize)
Definition: SimpleMatrix.h:270
NeuronID * get_row_begin(NeuronID i)
Definition: SimpleMatrix.h:586
T * get_value_ptr(NeuronID i)
Definition: SimpleMatrix.h:680
void print()
Definition: SimpleMatrix.h:648
unsigned int NeuronID
NeuronID is an unsigned integeger type used to index neurons in Auryn.
Definition: auryn_definitions.h:151