hsyncnet.py
1 """!
2 
3 @brief Cluster analysis algorithm: Hierarchical Sync (HSyncNet)
4 @details Implementation based on paper @cite artcile::hsyncnet::1.
5 
6 @authors Andrei Novikov (pyclustering@yandex.ru)
7 @date 2014-2018
8 @copyright GNU Public License
9 
10 @cond GNU_PUBLIC_LICENSE
11  PyClustering is free software: you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  PyClustering is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program. If not, see <http://www.gnu.org/licenses/>.
23 @endcond
24 
25 """
26 
27 
28 import pyclustering.core.hsyncnet_wrapper as wrapper;
29 
30 from pyclustering.core.wrapper import ccore_library;
31 
32 from pyclustering.nnet import initial_type, solve_type;
33 
34 from pyclustering.cluster.syncnet import syncnet, syncnet_analyser;
35 
36 from pyclustering.utils import average_neighbor_distance;
37 
38 
40  """!
41  @brief Class represents clustering algorithm HSyncNet. HSyncNet is bio-inspired algorithm that is based on oscillatory network that uses modified Kuramoto model.
42 
43  @details CCORE option can be used to use the pyclustering core - C/C++ shared library for processing that significantly increases performance.
44 
45  Example:
46  @code
47  # read list of points for cluster analysis
48  sample = read_sample(file);
49 
50  # create network for allocation three clusters using CCORE (C++ implementation)
51  network = hsyncnet(sample, 3, ccore = True);
52 
53  # run cluster analysis and output dynamic of the network
54  (time, dynamic) = network.process(0.995, collect_dynamic = True);
55 
56  # get allocated clusters
57  clusters = network.get_clusters();
58 
59  # show output dynamic of the network
60  draw_dynamics(time, dynamic);
61  @endcode
62  """
63 
64  def __init__(self, source_data, number_clusters, osc_initial_phases = initial_type.RANDOM_GAUSSIAN, initial_neighbors = 3, increase_persent = 0.15, ccore = True):
65  """!
66  @brief Costructor of the oscillatory network hSyncNet for cluster analysis.
67 
68  @param[in] source_data (list): Input data set defines structure of the network.
69  @param[in] number_clusters (uint): Number of clusters that should be allocated.
70  @param[in] osc_initial_phases (initial_type): Type of initialization of initial values of phases of oscillators.
71  @param[in] initial_neighbors (uint): Defines initial radius connectivity by calculation average distance to connect specify number of oscillators.
72  @param[in] increase_persent (double): Percent of increasing of radius connectivity on each step (input values in range (0.0; 1.0) correspond to (0%; 100%)).
73  @param[in] ccore (bool): If True than DLL CCORE (C++ solution) will be used for solving.
74 
75  """
76 
77  self.__ccore_network_pointer = None;
78 
79  if (initial_neighbors >= len(source_data)):
80  initial_neighbors = len(source_data) - 1;
81 
82  if ( (ccore is True) and ccore_library.workable() ):
83  self.__ccore_network_pointer = wrapper.hsyncnet_create_network(source_data, number_clusters, osc_initial_phases, initial_neighbors, increase_persent);
84  else:
85  super().__init__(source_data, 0, initial_phases = osc_initial_phases, ccore=False);
86 
87  self.__initial_neighbors = initial_neighbors;
88  self.__increase_persent = increase_persent;
89  self._number_clusters = number_clusters;
90 
91 
92  def __del__(self):
93  """!
94  @brief Destructor of oscillatory network HSyncNet.
95 
96  """
97 
98  if (self.__ccore_network_pointer is not None):
99  wrapper.hsyncnet_destroy_network(self.__ccore_network_pointer);
100  self.__ccore_network_pointer = None;
101 
102 
103  def process(self, order = 0.998, solution = solve_type.FAST, collect_dynamic = False):
104  """!
105  @brief Performs clustering of input data set in line with input parameters.
106 
107  @param[in] order (double): Level of local synchronization between oscillator that defines end of synchronization process, range [0..1].
108  @param[in] solution (solve_type) Type of solving differential equation.
109  @param[in] collect_dynamic (bool): If True - returns whole history of process synchronization otherwise - only final state (when process of clustering is over).
110 
111  @return (tuple) Returns dynamic of the network as tuple of lists on each iteration (time, oscillator_phases) that depends on collect_dynamic parameter.
112 
113  @see get_clusters()
114 
115  """
116 
117  if (self.__ccore_network_pointer is not None):
118  analyser = wrapper.hsyncnet_process(self.__ccore_network_pointer, order, solution, collect_dynamic);
119  return syncnet_analyser(None, None, analyser);
120 
121  number_neighbors = self.__initial_neighbors;
122  current_number_clusters = float('inf');
123 
124  dyn_phase = [];
125  dyn_time = [];
126 
127  radius = average_neighbor_distance(self._osc_loc, number_neighbors);
128 
129  increase_step = int(len(self._osc_loc) * self.__increase_persent);
130  if (increase_step < 1):
131  increase_step = 1;
132 
133 
134  analyser = None;
135  while(current_number_clusters > self._number_clusters):
136  self._create_connections(radius);
137 
138  analyser = self.simulate_dynamic(order, solution, collect_dynamic);
139  if (collect_dynamic == True):
140  if (len(dyn_phase) == 0):
141  self.__store_dynamic(dyn_phase, dyn_time, analyser, True);
142 
143  self.__store_dynamic(dyn_phase, dyn_time, analyser, False);
144 
145  clusters = analyser.allocate_sync_ensembles(0.05);
146 
147  # Get current number of allocated clusters
148  current_number_clusters = len(clusters);
149 
150  # Increase number of neighbors that should be used
151  number_neighbors += increase_step;
152 
153  # Update connectivity radius and check if average function can be used anymore
154  radius = self.__calculate_radius(number_neighbors, radius);
155 
156  if (collect_dynamic != True):
157  self.__store_dynamic(dyn_phase, dyn_time, analyser, False);
158 
159  return syncnet_analyser(dyn_phase, dyn_time, None);
160 
161 
162  def __calculate_radius(self, number_neighbors, radius):
163  """!
164  @brief Calculate new connectivity radius.
165 
166  @param[in] number_neighbors (uint): Average amount of neighbors that should be connected by new radius.
167  @param[in] radius (double): Current connectivity radius.
168 
169  @return New connectivity radius.
170 
171  """
172 
173  if (number_neighbors >= len(self._osc_loc)):
174  return radius * self.__increase_persent + radius;
175 
176  return average_neighbor_distance(self._osc_loc, number_neighbors);
177 
178 
179  def __store_dynamic(self, dyn_phase, dyn_time, analyser, begin_state):
180  """!
181  @brief Store specified state of Sync network to hSync.
182 
183  @param[in] dyn_phase (list): Output dynamic of hSync where state should be stored.
184  @param[in] dyn_time (list): Time points that correspond to output dynamic where new time point should be stored.
185  @param[in] analyser (syncnet_analyser): Sync analyser where Sync states are stored.
186  @param[in] begin_state (bool): If True the first state of Sync network is stored, otherwise the last state is stored.
187 
188  """
189 
190  if (begin_state is True):
191  dyn_time.append(0);
192  dyn_phase.append(analyser.output[0]);
193 
194  else:
195  dyn_phase.append(analyser.output[len(analyser.output) - 1]);
196  dyn_time.append(len(dyn_time));
def simulate_dynamic(self, order=0.998, solution=solve_type.FAST, collect_dynamic=False, step=0.1, int_step=0.01, threshold_changes=0.0000001)
Performs dynamic simulation of the network until stop condition is not reached.
Definition: sync.py:871
def __del__(self)
Destructor of oscillatory network HSyncNet.
Definition: hsyncnet.py:92
Utils that are used by modules of pyclustering.
Definition: __init__.py:1
Performs analysis of output dynamic of the oscillatory network syncnet to extract information about c...
Definition: syncnet.py:50
def __init__(self, source_data, number_clusters, osc_initial_phases=initial_type.RANDOM_GAUSSIAN, initial_neighbors=3, increase_persent=0.15, ccore=True)
Costructor of the oscillatory network hSyncNet for cluster analysis.
Definition: hsyncnet.py:64
Class represents clustering algorithm SyncNet.
Definition: syncnet.py:164
def __calculate_radius(self, number_neighbors, radius)
Calculate new connectivity radius.
Definition: hsyncnet.py:162
def __store_dynamic(self, dyn_phase, dyn_time, analyser, begin_state)
Store specified state of Sync network to hSync.
Definition: hsyncnet.py:179
def process(self, order=0.998, solution=solve_type.FAST, collect_dynamic=False)
Performs clustering of input data set in line with input parameters.
Definition: hsyncnet.py:103
Class represents clustering algorithm HSyncNet.
Definition: hsyncnet.py:39
Cluster analysis algorithm: Sync.
Definition: syncnet.py:1
Neural and oscillatory network module.
Definition: __init__.py:1
def _create_connections(self, radius)
Create connections between oscillators in line with input radius of connectivity. ...
Definition: syncnet.py:242