Completed
Push — 0.7.dev ( 54b342...f100af )
by Andrei
01:08
created

fsync_dynamic.__init__()   A

Complexity

Conditions 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
"""!
2
3
@brief Oscillatory Neural Network based on Kuramoto model in frequency domain.
4
@details Based on article description:
5
         - Y.Kuramoto. Chemical Oscillations, Waves, and Turbulence. 1984.
6
7
@authors Andrei Novikov ([email protected])
8
@date 2014-2017
9
@copyright GNU Public License
10
11
@cond GNU_PUBLIC_LICENSE
12
    PyClustering is free software: you can redistribute it and/or modify
13
    it under the terms of the GNU General Public License as published by
14
    the Free Software Foundation, either version 3 of the License, or
15
    (at your option) any later version.
16
    
17
    PyClustering is distributed in the hope that it will be useful,
18
    but WITHOUT ANY WARRANTY; without even the implied warranty of
19
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
    GNU General Public License for more details.
21
    
22
    You should have received a copy of the GNU General Public License
23
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
@endcond
25
26
"""
27
28
29
import numpy;
0 ignored issues
show
Configuration introduced by
The import numpy could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
30
import random;
31
32
from scipy.integrate import odeint;
0 ignored issues
show
Configuration introduced by
The import scipy.integrate could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
33
34
from pyclustering.nnet import network, conn_type, conn_represent, solve_type;
35
from pyclustering.utils import draw_dynamics, draw_dynamics_set;
36
37
38
class fsync_dynamic:
39
    """!
40
    @brief Represents output dynamic of Sync in frequency domain.
41
    
42
    """
43
44
45
    def __init__(self, amplitude, time):
46
        """!
47
        @brief Constructor of Sync dynamic in frequency domain.
48
        
49
        @param[in] amplitude (list): Dynamic of oscillators on each step of simulation.
50
        @param[in] time (list): Simulation time where each time-point corresponds to amplitude-point.
51
        
52
        """
53
54
        self.__amplitude = amplitude;
55
        self.__time = time;
56
57
58
    @property
59
    def output(self):
60
        """!
61
        @brief (list) Returns output dynamic of the Sync network (amplitudes of each oscillator in the network) during simulation.
62
        
63
        """
64
65
        return self.__amplitude;
66
67
68
    @property
69
    def time(self):
70
        """!
71
        @brief (list) Returns time-points corresponds to dynamic-points points.
72
        
73
        """
74
75
        return self.__time;
76
77
78
    def __len__(self):
79
        """!
80
        @brief (uint) Returns number of simulation steps that are stored in dynamic.
81
        
82
        """
83
        
84
        return len(self.__dynamic);
0 ignored issues
show
Bug introduced by
The Instance of fsync_dynamic does not seem to have a member named __dynamic.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
85
86
87
88
class fsync_visualizer:
89
    """!
90
    @brief Visualizer of output dynamic of sync network in frequency domain.
91
    
92
    """
93
94
    @staticmethod
95
    def show_output_dynamic(fsync_output_dynamic):
96
        """!
97
        @brief Shows output dynamic (output of each oscillator) during simulation.
98
        
99
        @param[in] fsync_output_dynamic (fsync_dynamic): Output dynamic of the fSync network.
100
        
101
        @see show_output_dynamics
102
        
103
        """
104
        
105
        draw_dynamics(fsync_output_dynamic.time, fsync_output_dynamic.output, x_title = "t", y_title = "amplitude");
106
107
108
    @staticmethod
109
    def show_output_dynamics(sync_output_dynamics):
110
        """!
111
        @brief Shows several output dynamics (output of each oscillator) during simulation.
112
        @details Each dynamic is presented on separate plot.
113
        
114
        @param[in] sync_output_dynamics (list): list of output dynamics 'fsync_dynamic' of the fSync network.
115
        
116
        @see show_output_dynamic
117
        
118
        """
119
        
120
        draw_dynamics_set(sync_output_dynamics, "t", "amplitude", None, None, False, False);
121
122
123
124
class fsync_network(network):
125
    """!
0 ignored issues
show
Bug introduced by
A suspicious escape sequence \d was found. Did you maybe forget to add an r prefix?

Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with r or R are they interpreted as regular expressions.

The escape sequence that was used indicates that you might have intended to write a regular expression.

Learn more about the available escape sequences. in the Python documentation.

Loading history...
Bug introduced by
A suspicious escape sequence \o was found. Did you maybe forget to add an r prefix?

Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with r or R are they interpreted as regular expressions.

The escape sequence that was used indicates that you might have intended to write a regular expression.

Learn more about the available escape sequences. in the Python documentation.

Loading history...
Bug introduced by
A suspicious escape sequence \s was found. Did you maybe forget to add an r prefix?

Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with r or R are they interpreted as regular expressions.

The escape sequence that was used indicates that you might have intended to write a regular expression.

Learn more about the available escape sequences. in the Python documentation.

Loading history...
126
    @brief Model of oscillatory network that uses Landau-Stuart oscillator and Kuramoto model as a synchronization mechanism.
127
    @details Dynamic of each oscillator in the network is described by following differential equation:
128
    
129
    \f[
130
    \dot{z}_{i} = (i\omega_{i} + \rho^{2}_{i} - |z_{i}|^{2} )z_{i} + \sum_{j=0}^{N}k_{ij}(z_{j} - z_{i})
131
    \f]
132
    
133
    """
134
    
135
    __DEFAULT_FREQUENCY_VALUE = 1.0;
136
    __DEFAULT_RADIUS_VALUE = 1.0;
137
    __DEFAULT_COUPLING_STRENGTH = 1.0;
138
139
140
    def __init__(self, num_osc, type_conn = conn_type.ALL_TO_ALL, representation = conn_represent.MATRIX):
141
        """!
142
        @brief Constructor of oscillatory network based on synchronization Kuramoto model and Landau-Stuart oscillator.
143
        
144
        @param[in] num_osc (uint): Amount oscillators in the network.
145
        @param[in] type_conn (conn_type): Type of connection between oscillators in the network (all-to-all, grid, bidirectional list, etc.).
146
        @param[in] representation (conn_represent): Internal representation of connection in the network: matrix or list.
147
        
148
        """
149
        
150
        super().__init__(num_osc, type_conn, representation);
151
        
152
        self.__frequency = fsync_network.__DEFAULT_FREQUENCY_VALUE;
153
        self.__radius = fsync_network.__DEFAULT_RADIUS_VALUE;
154
        self.__coupling_strength = fsync_network.__DEFAULT_COUPLING_STRENGTH;
155
        
156
        random.seed();
157
        self.__amplitude = [ random.random() for _ in range(num_osc) ];
158
159
160
    def simulate_static(self, steps, time, solution = solve_type.FAST, collect_dynamic = False):
161
        """!
162
        @brief Performs static simulation of oscillatory network.
163
        
164
        @param[in] steps (uint): Number simulation steps.
165
        @param[in] time (double): Time of simulation.
166
        @param[in] solution (solve_type): Type of method that is used to solve differential equation.
167
        @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.
168
        
169
        @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' is True, than return dynamic for the whole simulation time,
170
                otherwise returns only last values (last step of simulation) of output dynamic.
171
        
172
        @see simulate()
173
        @see simulate_dynamic()
174
        
175
        """
176
        
177
        dynamic_amplitude, dynamic_time = ([], []) if collect_dynamic is False else ([self.__amplitude], [0]);
178
        
179
        step = time / steps;
180
        int_step = step / 10.0;
181
        
182
        for t in numpy.arange(step, time + step, step):
183
            self.__amplitude = self.__calculate(solution, t, step, int_step);
184
            
185
            if (collect_dynamic == True):
186
                dynamic_amplitude.append(self.__amplitude);
187
                dynamic_time.append(t);
188
        
189
        if (collect_dynamic != True):
190
            dynamic_amplitude.append(self.__amplitude);
191
            dynamic_time.append(time);
192
193
        output_sync_dynamic = fsync_dynamic(dynamic_amplitude, dynamic_time);
194
        return output_sync_dynamic;
195
196
197 View Code Duplication
    def __calculate(self, solution, t, step, int_step):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
198
        """!
199
        @brief Calculates new amplitudes for oscillators in the network in line with current step.
200
        
201
        @param[in] solution (solve_type): Type solver of the differential equation.
202
        @param[in] t (double): Time of simulation.
203
        @param[in] step (double): Step of solution at the end of which states of oscillators should be calculated.
204
        @param[in] int_step (double): Step differentiation that is used for solving differential equation.
205
        
206
        @return (list) New states (phases) for oscillators.
207
        
208
        """
209
        
210
        next_amplitudes = [0.0] * self._num_osc;
211
        
212
        for index in range (0, self._num_osc, 1):
213
            if (solution == solve_type.FAST):
214
                next_amplitudes[index] = self.__amplitude[index] + self.__calculate_amplitude(self.__amplitude[index], 0, index);
215
                
216
            elif (solution == solve_type.RK4):
217
                result = odeint(self.__calculate_amplitude, self.__amplitude[index], numpy.arange(t - step, t, int_step), (index , ));
218
                next_amplitudes[index] = result[len(result) - 1][0];
219
            
220
            else:
221
                raise NameError("Solver '" + solution + "' is not supported");
222
        
223
        return next_amplitudes;
224
225
226
    def __landau_stuart(self, amplitude, index):
0 ignored issues
show
Unused Code introduced by
The argument index seems to be unused.
Loading history...
227
        """!
228
        @brief Calculate Landau-Stuart state.
229
        
230
        @param[in] amplitude (double): Current amplitude of oscillator.
231
        @param[in] index (uint): Oscillator index whose state is calculated. 
232
        
233
        @return (double) Landau-Stuart state.
234
        
235
        """
236
        
237
        return (self.__frequency + self.__radius**2 - abs(amplitude)**2) * amplitude;
238
239
240
    def __synchronization_mechanism(self, amplitude, index):
241
        """!
242
        @brief Calculate synchronization part using Kuramoto synchronization mechanism.
243
        
244
        @param[in] amplitude (double): Current amplitude of oscillator.
245
        @param[in] index (uint): Oscillator index whose synchronization influence is calculated.
246
        
247
        @return (double) Synchronization influence for the specified oscillator.
248
        
249
        """
250
        
251
        sync_influence = 0.0;
252
        
253
        for k in range(self._num_osc):
254
            if (self.has_connection(index, k) == True):
255
                sync_influence += amplitude - self.__amplitude[k];
256
        
257
        return sync_influence * self.__coupling_strength / self._num_osc;
258
259
260
    def __calculate_amplitude(self, amplitude, t, argv):
0 ignored issues
show
Unused Code introduced by
The argument t seems to be unused.
Loading history...
261
        """!
262
        @brief Returns new amplitude value for particular oscillator that is defined by index that is in 'argv' argument.
263
        @details The method is used for differential calculation.
264
        
265
        @param[in] amplitude (double): Current amplitude of oscillator.
266
        @param[in] t (double): Current time of simulation.
267
        @param[in] argv (uint): Index of the current oscillator.
268
        
269
        @return (double) New amplitude of the oscillator.
270
        
271
        """
272
        return self.__landau_stuart(amplitude, argv) + self.__synchronization_mechanism(amplitude, argv);