pyclustering  0.10.1
pyclustring is a Python, C++ data mining library.
__init__.py
1 """!
2 
3 @brief Neural and oscillatory network module. Consists of models of bio-inspired networks.
4 
5 @authors Andrei Novikov (pyclustering@yandex.ru)
6 @date 2014-2020
7 @copyright BSD-3-Clause
8 
9 """
10 
11 import math;
12 
13 from enum import IntEnum;
14 
15 class initial_type(IntEnum):
16  """!
17  @brief Enumerator of types of oscillator output initialization.
18 
19  """
20 
21 
22  RANDOM_GAUSSIAN = 0;
23 
24 
25  EQUIPARTITION = 1;
26 
27 
28 class solve_type(IntEnum):
29  """!
30  @brief Enumerator of solver types that are used for network simulation.
31 
32  """
33 
34 
35  FAST = 0; # Usual calculation: x(k + 1) = x(k) + f(x(k)).
36 
37 
38  RK4 = 1;
39 
40 
41  RKF45 = 2;
42 
43 
44 class conn_type(IntEnum):
45  """!
46  @brief Enumerator of connection types between oscillators.
47 
48  """
49 
50 
51  NONE = 0;
52 
53 
54  ALL_TO_ALL = 1;
55 
56 
57  GRID_FOUR = 2;
58 
59 
60  GRID_EIGHT = 3;
61 
62 
63  LIST_BIDIR = 4;
64 
65 
66  DYNAMIC = 5;
67 
68 
69 class conn_represent(IntEnum):
70  """!
71  @brief Enumerator of internal network connection representation between oscillators.
72 
73  """
74 
75 
76  LIST = 0;
77 
78 
79  MATRIX = 1;
80 
81 
82 class network:
83  """!
84  @brief Common network description that consists of information about oscillators and connection between them.
85 
86  """
87 
88  _num_osc = 0;
89 
90  _osc_conn = None;
91  _conn_represent = None;
92  __conn_type = None;
93 
94  __height = 0;
95  __width = 0;
96 
97 
98  @property
99  def height(self):
100  """!
101  @brief Height of the network grid (that is defined by amout of oscillators in each column), this value is zero in case of non-grid structure.
102 
103  @note This property returns valid value only for network with grid structure.
104 
105  """
106  return self.__height;
107 
108 
109  @property
110  def width(self):
111  """!
112  @brief Width of the network grid, this value is zero in case of non-grid structure.
113 
114  @note This property returns valid value only for network with grid structure.
115 
116  """
117  return self.__width;
118 
119 
120  @property
121  def structure(self):
122  """!
123  @brief Type of network structure that is used for connecting oscillators.
124 
125  """
126  return self.__conn_type;
127 
128 
129  def __init__(self, num_osc, type_conn = conn_type.ALL_TO_ALL, conn_repr = conn_represent.MATRIX, height = None, width = None):
130  """!
131  @brief Constructor of the network.
132 
133  @param[in] num_osc (uint): Number of oscillators in the network that defines size of the network.
134  @param[in] type_conn (conn_type): Type of connections that are used in the network between oscillators.
135  @param[in] conn_repr (conn_represent): Type of representation of connections.
136  @param[in] height (uint): Number of oscillators in column of the network, this argument is used
137  only for network with grid structure (GRID_FOUR, GRID_EIGHT), for other types this argument is ignored.
138  @param[in] width (uint): Number of oscillotors in row of the network, this argument is used only
139  for network with grid structure (GRID_FOUR, GRID_EIGHT), for other types this argument is ignored.
140 
141  """
142 
143  self._num_osc = num_osc;
144  self._conn_represent = conn_repr;
145  self.__conn_type = type_conn;
146 
147  if (conn_repr is None):
148  self._conn_represent = conn_represent.MATRIX;
149 
150  if ( (type_conn == conn_type.GRID_EIGHT) or (type_conn == conn_type.GRID_FOUR) ):
151  if ( (height is not None) and (width is not None) ):
152  self.__height = height;
153  self.__width = width;
154  else:
155  side_size = self._num_osc ** (0.5);
156  if (side_size - math.floor(side_size) > 0):
157  raise NameError("Invalid number of oscillators '" + str(num_osc) + "' in the network in case of grid structure (root square should be extractable for the number of oscillators).");
158 
159  self.__height = int(side_size);
160  self.__width = self.__height;
161 
162  if (self.__height * self.__width != self._num_osc):
163  raise NameError('Width (' + str(self.__width) + ') x Height (' + str(self.__height) + ') must be equal to Size (' + str(self._num_osc) + ') in case of grid structure');
164 
165  self._create_structure(type_conn);
166 
167 
168  def __len__(self):
169  """!
170  @brief Returns size of the network that is defined by amount of oscillators.
171 
172  """
173  return self._num_osc;
174 
175 
176  def __create_connection(self, index1, index2):
177  if (self._conn_represent == conn_represent.MATRIX):
178  self._osc_conn[index1][index2] = True;
179  else:
180  self._osc_conn[index1].append(index2);
181 
182 
183  def __create_all_to_all_connections(self):
184  """!
185  @brief Creates connections between all oscillators.
186 
187  """
188 
189  if (self._conn_represent == conn_represent.MATRIX):
190  for index in range(0, self._num_osc, 1):
191  self._osc_conn.append([True] * self._num_osc);
192  self._osc_conn[index][index] = False;
193 
194  elif (self._conn_represent == conn_represent.LIST):
195  for index in range(0, self._num_osc, 1):
196  self._osc_conn.append([neigh for neigh in range(0, self._num_osc, 1) if index != neigh]);
197 
198 
199  def __create_grid_four_connections(self):
200  """!
201  @brief Creates network with connections that make up four grid structure.
202  @details Each oscillator may be connected with four neighbors in line with 'grid' structure: right, upper, left, lower.
203 
204  """
205 
206  side_size = self.__width;
207  if (self._conn_represent == conn_represent.MATRIX):
208  self._osc_conn = [[0] * self._num_osc for index in range(0, self._num_osc, 1)];
209  elif (self._conn_represent == conn_represent.LIST):
210  self._osc_conn = [[] for index in range(0, self._num_osc, 1)];
211  else:
212  raise NameError("Unknown type of representation of connections");
213 
214  for index in range(0, self._num_osc, 1):
215  upper_index = index - side_size;
216  lower_index = index + side_size;
217  left_index = index - 1;
218  right_index = index + 1;
219 
220  node_row_index = math.ceil(index / side_size);
221  if (upper_index >= 0):
222  self.__create_connection(index, upper_index);
223 
224  if (lower_index < self._num_osc):
225  self.__create_connection(index, lower_index);
226 
227  if ( (left_index >= 0) and (math.ceil(left_index / side_size) == node_row_index) ):
228  self.__create_connection(index, left_index);
229 
230  if ( (right_index < self._num_osc) and (math.ceil(right_index / side_size) == node_row_index) ):
231  self.__create_connection(index, right_index);
232 
233 
234  def __create_grid_eight_connections(self):
235  """!
236  @brief Creates network with connections that make up eight grid structure.
237  @details Each oscillator may be connected with eight neighbors in line with grid structure: right, right-upper, upper, upper-left, left, left-lower, lower, lower-right.
238 
239  """
240 
241  self.__create_grid_four_connections(); # create connection with right, upper, left, lower.
242  side_size = self.__width;
243 
244  for index in range(0, self._num_osc, 1):
245  upper_left_index = index - side_size - 1;
246  upper_right_index = index - side_size + 1;
247 
248  lower_left_index = index + side_size - 1;
249  lower_right_index = index + side_size + 1;
250 
251  node_row_index = math.floor(index / side_size);
252  upper_row_index = node_row_index - 1;
253  lower_row_index = node_row_index + 1;
254 
255  if ( (upper_left_index >= 0) and (math.floor(upper_left_index / side_size) == upper_row_index) ):
256  self.__create_connection(index, upper_left_index);
257 
258  if ( (upper_right_index >= 0) and (math.floor(upper_right_index / side_size) == upper_row_index) ):
259  self.__create_connection(index, upper_right_index);
260 
261  if ( (lower_left_index < self._num_osc) and (math.floor(lower_left_index / side_size) == lower_row_index) ):
262  self.__create_connection(index, lower_left_index);
263 
264  if ( (lower_right_index < self._num_osc) and (math.floor(lower_right_index / side_size) == lower_row_index) ):
265  self.__create_connection(index, lower_right_index);
266 
267 
268  def __create_list_bidir_connections(self):
269  """!
270  @brief Creates network as bidirectional list.
271  @details Each oscillator may be conneted with two neighbors in line with classical list structure: right, left.
272 
273  """
274 
275  if (self._conn_represent == conn_represent.MATRIX):
276  for index in range(0, self._num_osc, 1):
277  self._osc_conn.append([0] * self._num_osc);
278  self._osc_conn[index][index] = False;
279  if (index > 0):
280  self._osc_conn[index][index - 1] = True;
281 
282  if (index < (self._num_osc - 1)):
283  self._osc_conn[index][index + 1] = True;
284 
285  elif (self._conn_represent == conn_represent.LIST):
286  for index in range(self._num_osc):
287  self._osc_conn.append([]);
288  if (index > 0):
289  self._osc_conn[index].append(index - 1);
290 
291  if (index < (self._num_osc - 1)):
292  self._osc_conn[index].append(index + 1);
293 
294 
295  def __create_none_connections(self):
296  """!
297  @brief Creates network without connections.
298 
299  """
300  if (self._conn_represent == conn_represent.MATRIX):
301  for _ in range(0, self._num_osc, 1):
302  self._osc_conn.append([False] * self._num_osc);
303  elif (self._conn_represent == conn_represent.LIST):
304  self._osc_conn = [[] for _ in range(0, self._num_osc, 1)];
305 
306 
307  def __create_dynamic_connection(self):
308  """!
309  @brief Prepare storage for dynamic connections.
310 
311  """
312  if (self._conn_represent == conn_represent.MATRIX):
313  for _ in range(0, self._num_osc, 1):
314  self._osc_conn.append([False] * self._num_osc);
315  elif (self._conn_represent == conn_represent.LIST):
316  self._osc_conn = [[] for _ in range(0, self._num_osc, 1)];
317 
318 
319  def _create_structure(self, type_conn = conn_type.ALL_TO_ALL):
320  """!
321  @brief Creates connection in line with representation of matrix connections [NunOsc x NumOsc].
322 
323  @param[in] type_conn (conn_type): Connection type (all-to-all, bidirectional list, grid structure, etc.) that is used by the network.
324 
325  """
326 
327  self._osc_conn = list();
328 
329  if (type_conn == conn_type.NONE):
331 
332  elif (type_conn == conn_type.ALL_TO_ALL):
334 
335  elif (type_conn == conn_type.GRID_FOUR):
337 
338  elif (type_conn == conn_type.GRID_EIGHT):
340 
341  elif (type_conn == conn_type.LIST_BIDIR):
343 
344  elif (type_conn == conn_type.DYNAMIC):
346 
347  else:
348  raise NameError('The unknown type of connections');
349 
350 
351  def has_connection(self, i, j):
352  """!
353  @brief Returns True if there is connection between i and j oscillators and False - if connection doesn't exist.
354 
355  @param[in] i (uint): index of an oscillator in the network.
356  @param[in] j (uint): index of an oscillator in the network.
357 
358  """
359  if (self._conn_represent == conn_represent.MATRIX):
360  return (self._osc_conn[i][j]);
361 
362  elif (self._conn_represent == conn_represent.LIST):
363  for neigh_index in range(0, len(self._osc_conn[i]), 1):
364  if (self._osc_conn[i][neigh_index] == j):
365  return True;
366  return False;
367 
368  else:
369  raise NameError("Unknown type of representation of coupling");
370 
371 
372  def set_connection(self, i, j):
373  """!
374  @brief Couples two specified oscillators in the network with dynamic connections.
375 
376  @param[in] i (uint): index of an oscillator that should be coupled with oscillator 'j' in the network.
377  @param[in] j (uint): index of an oscillator that should be coupled with oscillator 'i' in the network.
378 
379  @note This method can be used only in case of DYNAMIC connections, otherwise it throws expection.
380 
381  """
382 
383  if (self.structure != conn_type.DYNAMIC):
384  raise NameError("Connection between oscillators can be changed only in case of dynamic type.");
385 
386  if (self._conn_represent == conn_represent.MATRIX):
387  self._osc_conn[i][j] = True;
388  self._osc_conn[j][i] = True;
389  else:
390  self._osc_conn[i].append(j);
391  self._osc_conn[j].append(i);
392 
393 
394  def get_neighbors(self, index):
395  """!
396  @brief Finds neighbors of the oscillator with specified index.
397 
398  @param[in] index (uint): index of oscillator for which neighbors should be found in the network.
399 
400  @return (list) Indexes of neighbors of the specified oscillator.
401 
402  """
403 
404  if (self._conn_represent == conn_represent.LIST):
405  return self._osc_conn[index]; # connections are represented by list.
406  elif (self._conn_represent == conn_represent.MATRIX):
407  return [neigh_index for neigh_index in range(self._num_osc) if self._osc_conn[index][neigh_index] == True];
408  else:
409  raise NameError("Unknown type of representation of connections");
pyclustering.nnet.network.__create_none_connections
def __create_none_connections(self)
Creates network without connections.
Definition: __init__.py:295
pyclustering.nnet.network._osc_conn
_osc_conn
Definition: __init__.py:90
pyclustering.nnet.network.__create_grid_eight_connections
def __create_grid_eight_connections(self)
Creates network with connections that make up eight grid structure.
Definition: __init__.py:234
pyclustering.nnet.network.__conn_type
__conn_type
Definition: __init__.py:92
pyclustering.nnet.initial_type
Enumerator of types of oscillator output initialization.
Definition: __init__.py:15
pyclustering.nnet.network._num_osc
int _num_osc
Definition: __init__.py:88
pyclustering.nnet.network.__len__
def __len__(self)
Returns size of the network that is defined by amount of oscillators.
Definition: __init__.py:168
pyclustering.nnet.conn_represent
Enumerator of internal network connection representation between oscillators.
Definition: __init__.py:69
pyclustering.nnet.network.__create_connection
def __create_connection(self, index1, index2)
Definition: __init__.py:176
pyclustering.nnet.network.__height
int __height
Definition: __init__.py:94
pyclustering.nnet.solve_type
Enumerator of solver types that are used for network simulation.
Definition: __init__.py:28
pyclustering.nnet.network.__init__
def __init__(self, num_osc, type_conn=conn_type.ALL_TO_ALL, conn_repr=conn_represent.MATRIX, height=None, width=None)
Constructor of the network.
Definition: __init__.py:129
pyclustering.nnet.network.__create_grid_four_connections
def __create_grid_four_connections(self)
Creates network with connections that make up four grid structure.
Definition: __init__.py:199
pyclustering.nnet.network.__width
int __width
Definition: __init__.py:95
pyclustering.nnet.network._conn_represent
_conn_represent
Definition: __init__.py:91
pyclustering.nnet.network
Common network description that consists of information about oscillators and connection between them...
Definition: __init__.py:82
pyclustering.nnet.network.get_neighbors
def get_neighbors(self, index)
Finds neighbors of the oscillator with specified index.
Definition: __init__.py:394
pyclustering.nnet.network.has_connection
def has_connection(self, i, j)
Returns True if there is connection between i and j oscillators and False - if connection doesn't exi...
Definition: __init__.py:351
pyclustering.nnet.network.__create_list_bidir_connections
def __create_list_bidir_connections(self)
Creates network as bidirectional list.
Definition: __init__.py:268
pyclustering.nnet.network.set_connection
def set_connection(self, i, j)
Couples two specified oscillators in the network with dynamic connections.
Definition: __init__.py:372
pyclustering.nnet.network.structure
def structure(self)
Type of network structure that is used for connecting oscillators.
Definition: __init__.py:121
pyclustering.nnet.conn_type
Enumerator of connection types between oscillators.
Definition: __init__.py:44
pyclustering.nnet.network.__create_all_to_all_connections
def __create_all_to_all_connections(self)
Creates connections between all oscillators.
Definition: __init__.py:183
pyclustering.nnet.network.width
def width(self)
Width of the network grid, this value is zero in case of non-grid structure.
Definition: __init__.py:110
pyclustering.nnet.network._create_structure
def _create_structure(self, type_conn=conn_type.ALL_TO_ALL)
Creates connection in line with representation of matrix connections [NunOsc x NumOsc].
Definition: __init__.py:319
pyclustering.nnet.network.__create_dynamic_connection
def __create_dynamic_connection(self)
Prepare storage for dynamic connections.
Definition: __init__.py:307
pyclustering.nnet.network.height
def height(self)
Height of the network grid (that is defined by amout of oscillators in each column),...
Definition: __init__.py:99