3 @brief Neural Network: Oscillatory Neural Network based on Kuramoto model
4 @details Implementation based on paper @cite article::syncnet::1, @cite article::nnet::sync::1, @cite inproceedings::net::sync::1.
6 @authors Andrei Novikov (pyclustering@yandex.ru)
8 @copyright BSD-3-Clause
16 import matplotlib.pyplot
as plt
17 import matplotlib.animation
as animation
19 import pyclustering.core.sync_wrapper
as wrapper
21 from pyclustering.core.wrapper
import ccore_library
23 from scipy.integrate
import odeint
25 from pyclustering.nnet import network, conn_represent, conn_type, initial_type, solve_type
31 @brief Provides services to calculate order parameter and local order parameter that are used
32 for synchronization level estimation.
38 @brief Calculates level of global synchronization (order parameter) for input phases.
39 @details This parameter is tend 1.0 when the oscillatory network close to global synchronization and it tend to 0.0 when
40 desynchronization is observed in the network.
42 @param[in] oscillator_phases (list): List of oscillator phases that are used for level of global synchronization.
44 @return (double) Level of global synchronization (order parameter).
46 @see calculate_order_parameter()
53 for phase
in oscillator_phases:
54 exp_amount += math.expm1(abs(1j * phase))
55 average_phase += phase
57 exp_amount /= len(oscillator_phases)
58 average_phase = math.expm1(abs(1j * (average_phase / len(oscillator_phases))))
60 return abs(average_phase) / abs(exp_amount)
66 @brief Calculates level of local synchorization (local order parameter) for input phases for the specified network.
67 @details This parameter is tend 1.0 when the oscillatory network close to local synchronization and it tend to 0.0 when
68 desynchronization is observed in the network.
70 @param[in] oscillator_phases (list): List of oscillator phases that are used for level of local (partial) synchronization.
71 @param[in] oscillatory_network (sync): Instance of oscillatory network whose connections are required for calculation.
73 @return (double) Level of local synchronization (local order parameter).
80 for i
in range(0, len(oscillatory_network), 1):
81 for j
in range(0, len(oscillatory_network), 1):
82 if oscillatory_network.has_connection(i, j)
is True:
83 exp_amount += math.exp(-abs(oscillator_phases[j] - oscillator_phases[i]))
89 return exp_amount / num_neigh
95 @brief Represents output dynamic of Sync.
102 @brief (list) Returns output dynamic of the Sync network (phase coordinates of each oscillator in the network) during simulation.
114 @brief (list) Returns sampling times when dynamic is measured during simulation.
125 @brief Constructor of Sync dynamic.
127 @param[in] phase (list): Dynamic of oscillators on each step of simulation. If ccore pointer is specified than it can be ignored.
128 @param[in] time (list): Simulation time.
129 @param[in] ccore (ctypes.pointer): Pointer to CCORE sync_dynamic instance in memory.
140 @brief Default destructor of Sync dynamic.
149 @brief Returns number of simulation steps that are stored in dynamic.
150 @return (uint) Number of simulation steps that are stored in dynamic.
161 @brief Indexing of the dynamic.
171 raise NameError(
'Out of range ' + index +
': only indexes 0 and 1 are supported.')
176 @brief Allocate clusters in line with ensembles of synchronous oscillators where each synchronous ensemble corresponds to only one cluster.
178 @param[in] tolerance (double): Maximum error for allocation of synchronous ensemble oscillators.
179 @param[in] indexes (list): List of real object indexes and it should be equal to amount of oscillators (in case of 'None' - indexes are in range [0; amount_oscillators]).
180 @param[in] iteration (uint): Iteration of simulation that should be used for allocation.
182 @return (list) Groups (lists) of indexes of synchronous oscillators.
183 For example [ [index_osc1, index_osc3], [index_osc2], [index_osc4, index_osc5] ].
190 if indexes
is not None:
191 for ensemble
in ensembles:
192 for index
in range(len(ensemble)):
193 ensemble[index] = indexes[ensemble[index]]
200 number_oscillators = len(self.
_dynamic[0])
203 if iteration
is None:
206 last_state = self.
_dynamic[iteration]
209 if number_oscillators > 0:
212 for i
in range(1, number_oscillators, 1):
213 cluster_allocated =
False
214 for cluster
in clusters:
215 for neuron_index
in cluster:
216 last_state_shifted = abs(last_state[i] - 2 * pi)
218 if ( ( (last_state[i] < (last_state[neuron_index] + tolerance))
and (last_state[i] > (last_state[neuron_index] - tolerance)) )
or
219 ( (last_state_shifted < (last_state[neuron_index] + tolerance))
and (last_state_shifted > (last_state[neuron_index] - tolerance)) ) ):
220 cluster_allocated =
True
223 if indexes
is not None:
224 real_index = indexes[i]
226 cluster.append(real_index)
229 if cluster_allocated
is True:
232 if cluster_allocated
is False:
240 @brief Returns 2D matrix of phase values of oscillators at the specified iteration of simulation.
241 @details User should ensure correct matrix sizes in line with following expression grid_width x grid_height that should be equal to
242 amount of oscillators otherwise exception is thrown. If grid_width or grid_height are not specified than phase matrix size
243 will by calculated automatically by square root.
245 @param[in] grid_width (uint): Width of the allocated matrix.
246 @param[in] grid_height (uint): Height of the allocated matrix.
247 @param[in] iteration (uint): Number of iteration of simulation for which correlation matrix should be allocated.
248 If iternation number is not specified, the last step of simulation is used for the matrix allocation.
250 @return (list) Phase value matrix of oscillators with size [number_oscillators x number_oscillators].
254 output_dynamic = self.
output
256 if (output_dynamic
is None)
or (len(output_dynamic) == 0):
259 current_dynamic = output_dynamic[len(output_dynamic) - 1]
260 if iteration
is not None:
261 current_dynamic = output_dynamic[iteration]
263 width_matrix = grid_width
264 height_matrix = grid_height
265 number_oscillators = len(current_dynamic)
266 if (width_matrix
is None)
or (height_matrix
is None):
267 width_matrix = int(math.ceil(math.sqrt(number_oscillators)))
268 height_matrix = width_matrix
270 if (number_oscillators != width_matrix * height_matrix):
271 raise NameError(
"Impossible to allocate phase matrix with specified sizes, amout of neurons should be equal to grid_width * grid_height.");
273 phase_matrix = [[0.0
for _
in range(width_matrix)]
for _
in range(height_matrix)]
274 for i
in range(height_matrix):
275 for j
in range(width_matrix):
276 phase_matrix[i][j] = current_dynamic[j + i * width_matrix]
283 @brief Allocate correlation matrix between oscillators at the specified step of simulation.
285 @param[in] iteration (uint): Number of iteration of simulation for which correlation matrix should be allocated.
286 If iternation number is not specified, the last step of simulation is used for the matrix allocation.
288 @return (list) Correlation matrix between oscillators with size [number_oscillators x number_oscillators].
299 current_dynamic = dynamic[len(dynamic) - 1]
301 if iteration
is not None:
302 current_dynamic = dynamic[iteration]
304 number_oscillators = len(dynamic[0])
305 affinity_matrix = [[0.0
for i
in range(number_oscillators)]
for j
in range(number_oscillators)]
307 for i
in range(number_oscillators):
308 for j
in range(number_oscillators):
309 phase1 = current_dynamic[i]
310 phase2 = current_dynamic[j]
312 affinity_matrix[i][j] = abs(math.sin(phase1 - phase2))
314 return affinity_matrix
319 @brief Calculates level of global synchorization (order parameter).
320 @details This parameter is tend 1.0 when the oscillatory network close to global synchronization and it tend to 0.0 when
321 desynchronization is observed in the network. Order parameter is calculated using following equation:
324 r_{c}=\frac{1}{Ne^{i\varphi }}\sum_{j=0}^{N}e^{i\theta_{j}};
327 where \f$\varphi\f$ is a average phase coordinate in the network, \f$N\f$ is an amount of oscillators in the network.
329 @param[in] start_iteration (uint): The first iteration that is used for calculation, if 'None' then the last iteration is used.
330 @param[in] stop_iteration (uint): The last iteration that is used for calculation, if 'None' then 'start_iteration' + 1 is used.
334 oscillatory_network = sync(16, type_conn = conn_type.ALL_TO_ALL);
335 output_dynamic = oscillatory_network.simulate_static(100, 10);
337 print("Order parameter at the last step: ", output_dynamic.calculate_order_parameter());
338 print("Order parameter at the first step:", output_dynamic.calculate_order_parameter(0));
339 print("Order parameter evolution between 40 and 50 steps:", output_dynamic.calculate_order_parameter(40, 50));
342 @return (list) List of levels of global synchronization (order parameter evolution).
354 for index
in range(start_iteration, stop_iteration):
355 sequence_order.append(order_estimator.calculate_sync_order(self.
output[index]))
357 return sequence_order
362 @brief Calculates local order parameter.
363 @details Local order parameter or so-called level of local or partial synchronization is calculated by following expression:
366 r_{c}=\left | \sum_{i=0}^{N} \frac{1}{N_{i}} \sum_{j=0}e^{ \theta_{j} - \theta_{i} } \right |;
369 where N - total amount of oscillators in the network and \f$N_{i}\f$ - amount of neighbors of oscillator with index \f$i\f$.
371 @param[in] oscillatory_network (sync): Sync oscillatory network whose structure of connections is required for calculation.
372 @param[in] start_iteration (uint): The first iteration that is used for calculation, if 'None' then the last iteration is used.
373 @param[in] stop_iteration (uint): The last iteration that is used for calculation, if 'None' then 'start_iteration' + 1 is used.
375 @return (list) List of levels of local (partial) synchronization (local order parameter evolution).
382 network_pointer = oscillatory_network._ccore_network_pointer
383 return wrapper.sync_dynamic_calculate_local_order(self.
_ccore_sync_dynamic_pointer, network_pointer, start_iteration, stop_iteration)
385 sequence_local_order = []
386 for index
in range(start_iteration, stop_iteration):
387 sequence_local_order.append(order_estimator.calculate_local_sync_order(self.
output[index], oscillatory_network))
389 return sequence_local_order
392 def __get_start_stop_iterations(self, start_iteration, stop_iteration):
394 @brief Aplly rules for start_iteration and stop_iteration parameters.
396 @param[in] start_iteration (uint): The first iteration that is used for calculation.
397 @param[in] stop_iteration (uint): The last iteration that is used for calculation.
399 @return (tuple) New the first iteration and the last.
402 if start_iteration
is None:
403 start_iteration = len(self) - 1
405 if stop_iteration
is None:
406 stop_iteration = start_iteration + 1
408 return start_iteration, stop_iteration
414 @brief Visualizer of output dynamic of sync network (Sync).
421 @brief Shows output dynamic (output of each oscillator) during simulation.
423 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
425 @see show_output_dynamics
429 draw_dynamics(sync_output_dynamic.time, sync_output_dynamic.output, x_title=
"t", y_title=
"phase", y_lim=[0, 2 * 3.14])
435 @brief Shows several output dynamics (output of each oscillator) during simulation.
436 @details Each dynamic is presented on separate plot.
438 @param[in] sync_output_dynamics (list): list of output dynamics 'sync_dynamic' of the Sync network.
440 @see show_output_dynamic
444 draw_dynamics_set(sync_output_dynamics,
"t",
"phase",
None, [0, 2 * 3.14],
False,
False)
450 @brief Shows correlation matrix between oscillators at the specified iteration.
452 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
453 @param[in] iteration (uint): Number of iteration of simulation for which correlation matrix should be
454 allocated. If iteration number is not specified, the last step of simulation is used for the matrix
460 correlation_matrix = sync_output_dynamic.allocate_correlation_matrix(iteration)
462 plt.imshow(correlation_matrix, cmap = plt.get_cmap(
'cool'), interpolation=
'kaiser', vmin=0.0, vmax=1.0)
469 @brief Shows 2D matrix of phase values of oscillators at the specified iteration.
470 @details User should ensure correct matrix sizes in line with following expression grid_width x grid_height that should be equal to
471 amount of oscillators otherwise exception is thrown. If grid_width or grid_height are not specified than phase matrix size
472 will by calculated automatically by square root.
474 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network whose phase matrix should be shown.
475 @param[in] grid_width (uint): Width of the phase matrix.
476 @param[in] grid_height (uint): Height of the phase matrix.
477 @param[in] iteration (uint): Number of iteration of simulation for which correlation matrix should be allocated.
478 If iternation number is not specified, the last step of simulation is used for the matrix allocation.
483 phase_matrix = sync_output_dynamic.allocate_phase_matrix(grid_width, grid_height, iteration)
485 plt.imshow(phase_matrix, cmap = plt.get_cmap(
'jet'), interpolation=
'kaiser', vmin=0.0, vmax=2.0 * math.pi)
492 @brief Shows evolution of order parameter (level of global synchronization in the network).
494 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network whose evolution of global synchronization should be visualized.
495 @param[in] start_iteration (uint): The first iteration that is used for calculation, if 'None' then the first is used
496 @param[in] stop_iteration (uint): The last iteration that is used for calculation, if 'None' then the last is used.
500 (start_iteration, stop_iteration) = sync_visualizer.__get_start_stop_iterations(sync_output_dynamic, start_iteration, stop_iteration)
502 order_parameter = sync_output_dynamic.calculate_order_parameter(start_iteration, stop_iteration)
503 axis = plt.subplot(111)
504 plt.plot(sync_output_dynamic.time[start_iteration:stop_iteration], order_parameter,
'b-', linewidth=2.0)
505 set_ax_param(axis,
"t",
"R (order parameter)",
None, [0.0, 1.05])
513 @brief Shows evolution of local order parameter (level of local synchronization in the network).
515 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network whose evolution of global synchronization should be visualized.
516 @param[in] oscillatory_network (sync): Sync oscillatory network whose structure of connections is required for calculation.
517 @param[in] start_iteration (uint): The first iteration that is used for calculation, if 'None' then the first is used
518 @param[in] stop_iteration (uint): The last iteration that is used for calculation, if 'None' then the last is used.
521 (start_iteration, stop_iteration) = sync_visualizer.__get_start_stop_iterations(sync_output_dynamic, start_iteration, stop_iteration)
523 order_parameter = sync_output_dynamic.calculate_local_order_parameter(oscillatory_network, start_iteration, stop_iteration)
524 axis = plt.subplot(111)
525 plt.plot(sync_output_dynamic.time[start_iteration:stop_iteration], order_parameter,
'b-', linewidth=2.0)
526 set_ax_param(axis,
"t",
"R (local order parameter)",
None, [0.0, 1.05])
534 @brief Shows animation of output dynamic (output of each oscillator) during simulation on a circle from [0; 2pi].
536 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
537 @param[in] animation_velocity (uint): Interval between frames in milliseconds.
538 @param[in] save_movie (string): If it is specified then animation will be stored to file that is specified in this parameter.
542 figure = plt.figure()
544 dynamic = sync_output_dynamic.output[0]
545 artist, = plt.polar(dynamic, [1.0] * len(dynamic),
'o', color=
'blue')
550 def frame_generation(index_dynamic):
551 dynamic = sync_output_dynamic.output[index_dynamic]
552 artist.set_data(dynamic, [1.0] * len(dynamic))
556 phase_animation = animation.FuncAnimation(figure, frame_generation, len(sync_output_dynamic), interval = animation_velocity, init_func = init_frame, repeat_delay = 5000);
558 if save_movie
is not None:
559 phase_animation.save(save_movie, writer=
'ffmpeg', fps=15, bitrate=1500)
567 @brief Shows animation of correlation matrix between oscillators during simulation.
569 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
570 @param[in] animation_velocity (uint): Interval between frames in milliseconds.
571 @param[in] colormap (string): Name of colormap that is used by matplotlib ('gray', 'pink', 'cool', spring', etc.).
572 @param[in] save_movie (string): If it is specified then animation will be stored to file that is specified in this parameter.
576 figure = plt.figure()
578 correlation_matrix = sync_output_dynamic.allocate_correlation_matrix(0)
579 artist = plt.imshow(correlation_matrix, cmap = plt.get_cmap(colormap), interpolation=
'kaiser', vmin = 0.0, vmax = 1.0)
584 def frame_generation(index_dynamic):
585 correlation_matrix = sync_output_dynamic.allocate_correlation_matrix(index_dynamic)
586 artist.set_data(correlation_matrix)
590 correlation_animation = animation.FuncAnimation(figure, frame_generation, len(sync_output_dynamic), init_func = init_frame, interval = animation_velocity , repeat_delay = 1000, blit =
True)
592 if save_movie
is not None:
593 correlation_animation.save(save_movie, writer=
'ffmpeg', fps=15, bitrate=1500)
599 def animate_phase_matrix(sync_output_dynamic, grid_width=None, grid_height=None, animation_velocity=75, colormap='jet', save_movie=None):
601 @brief Shows animation of phase matrix between oscillators during simulation on 2D stage.
602 @details If grid_width or grid_height are not specified than phase matrix size will by calculated automatically by square root.
604 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
605 @param[in] grid_width (uint): Width of the phase matrix.
606 @param[in] grid_height (uint): Height of the phase matrix.
607 @param[in] animation_velocity (uint): Interval between frames in milliseconds.
608 @param[in] colormap (string): Name of colormap that is used by matplotlib ('gray', 'pink', 'cool', spring', etc.).
609 @param[in] save_movie (string): If it is specified then animation will be stored to file that is specified in this parameter.
613 figure = plt.figure()
616 return frame_generation(0)
618 def frame_generation(index_dynamic):
620 axis = figure.add_subplot(111)
622 phase_matrix = sync_output_dynamic.allocate_phase_matrix(grid_width, grid_height, index_dynamic)
623 axis.imshow(phase_matrix, cmap=plt.get_cmap(colormap), interpolation=
'kaiser', vmin=0.0, vmax=2.0 * math.pi)
624 artist = figure.gca()
628 phase_animation = animation.FuncAnimation(figure, frame_generation, len(sync_output_dynamic), init_func = init_frame, interval = animation_velocity , repeat_delay = 1000);
630 if save_movie
is not None:
631 phase_animation.save(save_movie, writer=
'ffmpeg', fps=15, bitrate=1500)
637 def __get_start_stop_iterations(sync_output_dynamic, start_iteration, stop_iteration):
639 @brief Apply rule of preparation for start iteration and stop iteration values.
641 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
642 @param[in] start_iteration (uint): The first iteration that is used for calculation.
643 @param[in] stop_iteration (uint): The last iteration that is used for calculation.
645 @return (tuple) New values of start and stop iterations.
648 if start_iteration
is None:
651 if stop_iteration
is None:
652 stop_iteration = len(sync_output_dynamic)
654 return start_iteration, stop_iteration
658 def animate(sync_output_dynamic, title=None, save_movie=None):
660 @brief Shows animation of phase coordinates and animation of correlation matrix together for the Sync dynamic output on the same figure.
662 @param[in] sync_output_dynamic (sync_dynamic): Output dynamic of the Sync network.
663 @param[in] title (string): Title of the animation that is displayed on a figure if it is specified.
664 @param[in] save_movie (string): If it is specified then animation will be stored to file that is specified in this parameter.
668 dynamic = sync_output_dynamic.output[0]
669 correlation_matrix = sync_output_dynamic.allocate_correlation_matrix(0)
671 figure = plt.figure(1)
672 if title
is not None:
673 figure.suptitle(title, fontsize = 26, fontweight =
'bold')
675 ax1 = figure.add_subplot(121, projection=
'polar')
676 ax2 = figure.add_subplot(122)
678 artist1, = ax1.plot(dynamic, [1.0] * len(dynamic), marker=
'o', color=
'blue', ls=
'')
679 artist2 = ax2.imshow(correlation_matrix, cmap = plt.get_cmap(
'Accent'), interpolation=
'kaiser')
682 return [artist1, artist2]
684 def frame_generation(index_dynamic):
685 dynamic = sync_output_dynamic.output[index_dynamic]
686 artist1.set_data(dynamic, [1.0] * len(dynamic))
688 correlation_matrix = sync_output_dynamic.allocate_correlation_matrix(index_dynamic)
689 artist2.set_data(correlation_matrix)
691 return [artist1, artist2]
693 dynamic_animation = animation.FuncAnimation(figure, frame_generation, len(sync_output_dynamic), interval=75, init_func=init_frame, repeat_delay=5000)
695 if save_movie
is not None:
696 dynamic_animation.save(save_movie, writer=
'ffmpeg', fps=15, bitrate=1500)
704 @brief Model of oscillatory network that is based on the Kuramoto model of synchronization.
706 @details CCORE option can be used to use the pyclustering core - C/C++ shared library for processing that significantly increases performance.
710 def __init__(self, num_osc, weight = 1, frequency = 0, type_conn = conn_type.ALL_TO_ALL, representation = conn_represent.MATRIX, initial_phases = initial_type.RANDOM_GAUSSIAN, ccore = True):
712 @brief Constructor of oscillatory network is based on Kuramoto model.
714 @param[in] num_osc (uint): Number of oscillators in the network.
715 @param[in] weight (double): Coupling strength of the links between oscillators.
716 @param[in] frequency (double): Multiplier of internal frequency of the oscillators.
717 @param[in] type_conn (conn_type): Type of connection between oscillators in the network (all-to-all, grid, bidirectional list, etc.).
718 @param[in] representation (conn_represent): Internal representation of connection in the network: matrix or list.
719 @param[in] initial_phases (initial_type): Type of initialization of initial phases of oscillators (random, uniformly distributed, etc.).
720 @param[in] ccore (bool): If True simulation is performed by CCORE library (C++ implementation of pyclustering).
726 if ( (ccore
is True)
and ccore_library.workable() ):
727 self.
_ccore_network_pointer = wrapper.sync_create_network(num_osc, weight, frequency, type_conn, initial_phases);
732 super().
__init__(num_osc, type_conn, representation);
740 for index
in range(0, num_osc, 1):
741 if (initial_phases == initial_type.RANDOM_GAUSSIAN):
742 self.
_phases.append(random.random() * 2 * pi);
744 elif (initial_phases == initial_type.EQUIPARTITION):
745 self.
_phases.append( pi / num_osc * index);
747 self.
_freq.append(random.random() * frequency);
752 @brief Destructor of oscillatory network is based on Kuramoto model.
763 @brief Calculates current level of global synchorization (order parameter) in the network.
764 @details This parameter is tend 1.0 when the oscillatory network close to global synchronization and it tend to 0.0 when
765 desynchronization is observed in the network. Order parameter is calculated using following equation:
768 r_{c}=\frac{1}{Ne^{i\varphi }}\sum_{j=0}^{N}e^{i\theta_{j}};
771 where \f$\varphi\f$ is a average phase coordinate in the network, \f$N\f$ is an amount of oscillators in the network.
775 oscillatory_network = sync(16, type_conn = conn_type.ALL_TO_ALL);
776 output_dynamic = oscillatory_network.simulate_static(100, 10);
778 if (oscillatory_network.sync_order() < 0.9): print("Global synchronization is not reached yet.");
779 else: print("Global synchronization is reached.");
782 @return (double) Level of global synchronization (order parameter).
784 @see sync_local_order()
791 return order_estimator.calculate_sync_order(self.
_phases);
796 @brief Calculates current level of local (partial) synchronization in the network.
798 @return (double) Level of local (partial) synchronization.
807 return order_estimator.calculate_local_sync_order(self.
_phases, self);
810 def _phase_kuramoto(self, teta, t, argv):
812 @brief Returns result of phase calculation for specified oscillator in the network.
814 @param[in] teta (double): Phase of the oscillator that is differentiated.
815 @param[in] t (double): Current time of simulation.
816 @param[in] argv (tuple): Index of the oscillator in the list.
818 @return (double) New phase for specified oscillator (don't assign here).
826 phase += math.sin(self.
_phases[k] - teta);
831 def simulate(self, steps, time, solution = solve_type.FAST, collect_dynamic = True):
833 @brief Performs static simulation of Sync oscillatory network.
835 @param[in] steps (uint): Number steps of simulations during simulation.
836 @param[in] time (double): Time of simulation.
837 @param[in] solution (solve_type): Type of solution (solving).
838 @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.
840 @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
841 otherwise returns only last values (last step of simulation) of dynamic.
843 @see simulate_dynamic()
844 @see simulate_static()
851 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):
853 @brief Performs dynamic simulation of the network until stop condition is not reached. Stop condition is defined by input argument 'order'.
855 @param[in] order (double): Order of process synchronization, distributed 0..1.
856 @param[in] solution (solve_type): Type of solution.
857 @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.
858 @param[in] step (double): Time step of one iteration of simulation.
859 @param[in] int_step (double): Integration step, should be less than step.
860 @param[in] threshold_changes (double): Additional stop condition that helps prevent infinite simulation, defines limit of changes of oscillators between current and previous steps.
862 @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
863 otherwise returns only last values (last step of simulation) of dynamic.
866 @see simulate_static()
871 ccore_instance_dynamic = wrapper.sync_simulate_dynamic(self.
_ccore_network_pointer, order, solution, collect_dynamic, step, int_step, threshold_changes);
872 return sync_dynamic(
None,
None, ccore_instance_dynamic);
884 if (collect_dynamic ==
True):
885 dyn_phase.append(self.
_phases);
889 while (current_order < order):
894 time_counter += step;
897 if (collect_dynamic ==
True):
898 dyn_phase.append(self.
_phases);
899 dyn_time.append(time_counter);
902 previous_order = current_order;
906 if (abs(current_order - previous_order) < threshold_changes):
910 if (collect_dynamic !=
True):
911 dyn_phase.append(self.
_phases);
912 dyn_time.append(time_counter);
914 output_sync_dynamic =
sync_dynamic(dyn_phase, dyn_time,
None);
915 return output_sync_dynamic;
918 def simulate_static(self, steps, time, solution = solve_type.FAST, collect_dynamic = False):
920 @brief Performs static simulation of oscillatory network.
922 @param[in] steps (uint): Number steps of simulations during simulation.
923 @param[in] time (double): Time of simulation.
924 @param[in] solution (solve_type): Type of solution.
925 @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.
927 @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
928 otherwise returns only last values (last step of simulation) of dynamic.
931 @see simulate_dynamic()
936 ccore_instance_dynamic = wrapper.sync_simulate_static(self.
_ccore_network_pointer, steps, time, solution, collect_dynamic);
937 return sync_dynamic(
None,
None, ccore_instance_dynamic);
942 if (collect_dynamic ==
True):
943 dyn_phase.append(self.
_phases);
947 int_step = step / 10.0;
949 for t
in numpy.arange(step, time + step, step):
954 if (collect_dynamic ==
True):
955 dyn_phase.append(self.
_phases);
958 if (collect_dynamic !=
True):
959 dyn_phase.append(self.
_phases);
960 dyn_time.append(time);
962 output_sync_dynamic =
sync_dynamic(dyn_phase, dyn_time);
963 return output_sync_dynamic;
966 def _calculate_phases(self, solution, t, step, int_step):
968 @brief Calculates new phases for oscillators in the network in line with current step.
970 @param[in] solution (solve_type): Type solver of the differential equation.
971 @param[in] t (double): Time of simulation.
972 @param[in] step (double): Step of solution at the end of which states of oscillators should be calculated.
973 @param[in] int_step (double): Step differentiation that is used for solving differential equation.
975 @return (list) New states (phases) for oscillators.
979 next_phases = [0.0] * self.
_num_osc;
981 for index
in range (0, self.
_num_osc, 1):
982 if (solution == solve_type.FAST):
986 elif ( (solution == solve_type.RK4)
or (solution == solve_type.RKF45) ):
987 result = odeint(self.
_phase_kuramoto, self.
_phases[index], numpy.arange(t - step, t, int_step), (index , ));
991 raise NameError(
"Solver '" + str(solution) +
"' is not supported");
996 def _phase_normalization(self, teta):
998 @brief Normalization of phase of oscillator that should be placed between [0; 2 * pi].
1000 @param[in] teta (double): phase of oscillator.
1002 @return (double) Normalized phase.
1007 while (norm_teta > (2.0 * pi))
or (norm_teta < 0):
1008 if (norm_teta > (2.0 * pi)):
1009 norm_teta -= 2.0 * pi;
1011 norm_teta += 2.0 * pi;
1018 @brief Finds neighbors of the oscillator with specified index.
1020 @param[in] index (uint): index of oscillator for which neighbors should be found in the network.
1022 @return (list) Indexes of neighbors of the specified oscillator.
1034 @brief Returns True if there is connection between i and j oscillators and False - if connection doesn't exist.
1036 @param[in] i (uint): index of an oscillator in the network.
1037 @param[in] j (uint): index of an oscillator in the network.