Completed
Push — master ( e69bed...5c451b )
by Andrei
01:54
created

cnn_visualizer.show_dynamic_matrix()   A

Complexity

Conditions 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
"""!
2
3
@brief Chaotic Neural Network
4
@details Based on article description:
5
         - 
6
7
@authors Andrei Novikov ([email protected])
8
@date 2014-2016
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
import matplotlib.pyplot as plt;
0 ignored issues
show
Configuration introduced by
The import matplotlib.pyplot 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...
29
import matplotlib.animation as animation;
0 ignored issues
show
Configuration introduced by
The import matplotlib.animation 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...
Unused Code introduced by
Unused matplotlib.animation imported as animation
Loading history...
30
31
import math;
32
import random;
33
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...
Unused Code introduced by
The import numpy seems to be unused.
Loading history...
34
35
from enum import IntEnum;
36
37
from pyclustering.utils import euclidean_distance_sqrt, average_neighbor_distance, heaviside, draw_dynamics;
38
39
40
class type_conn(IntEnum):
41
    """!
42
    @brief Enumeration of connection types for Chaotic Neural Network.
43
    
44
    @see cnn_network
45
    
46
    """
47
    
48
    ## All oscillators have connection with each other.
49
    ALL_TO_ALL  = 0,
50
    
51
    ## Connections between oscillators are created in line with Delaunay triangulation.
52
    TRIANGULATION_DELAUNAY = 1,
53
54
55
class cnn_dynamic:
56
    def __init__(self, output = [], time = []):
0 ignored issues
show
Bug Best Practice introduced by
The default value [] might cause unintended side-effects.

Objects as default values are only created once in Python and not on each invocation of the function. If the default object is modified, this modification is carried over to the next invocation of the method.

# Bad:
# If array_param is modified inside the function, the next invocation will
# receive the modified object.
def some_function(array_param=[]):
    # ...

# Better: Create an array on each invocation
def some_function(array_param=None):
    array_param = array_param or []
    # ...
Loading history...
57
        self.output = output;
58
        self.time = time;
59
60
61
    def __len__(self):
62
        return len(self.output);
63
64
65
    def allocate_observation_matrix(self):
66
        number_neurons = len(self.output[0]);
67
        observation_matrix = [];
68
        
69
        for iteration in range(len(self.output)):
70
            obervation_column = [];
71
            for index_neuron in range(number_neurons):
72
                obervation_column.append(heaviside(self.output[iteration][index_neuron]));
73
            
74
            observation_matrix.append(obervation_column);
75
        
76
        return observation_matrix;
77
78
79
class cnn_visualizer:
80
    @staticmethod
81
    def show_output_dynamic(cnn_output_dynamic):
82
        draw_dynamics(cnn_output_dynamic.time, cnn_output_dynamic.output, x_title = "t", y_title = "x");
83
    
84
    
85
    @staticmethod
86
    def show_dynamic_matrix(cnn_output_dynamic):
87
        plt.imshow(cnn_output_dynamic.output, cmap = plt.get_cmap('gray'), interpolation='None', vmin = 0.0, vmax = 1.0); 
88
        plt.show();
89
    
90
    
91
    @staticmethod
92
    def show_observation_matrix(cnn_output_dynamic):
93
        observation_matrix = cnn_output_dynamic.allocate_observation_matrix();
94
        plt.imshow(observation_matrix, cmap = plt.get_cmap('gray'), interpolation='None', vmin = 0.0, vmax = 1.0); 
95
        plt.show();
96
97
98
class cnn_network:
99
    def __init__(self, num_osc, conn_type = type_conn.ALL_TO_ALL, amount_neighbors = 3):
100
        self.__num_osc = num_osc;
101
        self.__conn_type = conn_type;
102
        self.__amount_neighbors = amount_neighbors;
103
        
104
        self.__average_distance = 0.0;
105
        self.__weights = None;
106
        self.__weights_summary = None;
107
        
108
        self.__output = [ random.random() for _ in range(num_osc) ];
109
    
110
    
111
    def __len__(self):
112
        return self.__num_osc;
113
    
114
    
115
    def simulate(self, steps, stimulus):
116
        self.__create_weights(stimulus);
117
        
118
        dynamic = cnn_dynamic([], []);
119
        dynamic.output.append(self.__output);
120
        dynamic.time.append(0);
121
        
122
        for step in range(1, steps, 1):
123
            self.__output = self.__calculate_states();
124
            
125
            dynamic.output.append(self.__output);
126
            dynamic.time.append(step);
127
            
128
        return dynamic;
129
    
130
    
131
    def __calculate_states(self):
132
        output = [ 0.0 for _ in range(self.__num_osc) ];
133
        
134
        for i in range(self.__num_osc):
135
            output[i] = self.__neuron_evolution(i);
136
        
137
        return output;
138
    
139
    
140
    def __neuron_evolution(self, index):
141
        value = 0.0;
142
        #state = 1.0 - 2.0 * (self.__output[index] ** 2);
143
        
144
        for index_neighbor in range(self.__num_osc):
145
            value += self.__weights[index][index_neighbor] * (1.0 - 2.0 * (self.__output[index_neighbor] ** 2));
146
        
147
        return value / self.__weights_summary[index];
148
    
149
    
150
    def __create_weights(self, stimulus):
151
        self.__average_distance = average_neighbor_distance(stimulus, self.__amount_neighbors);
152
        print("Average distance: ", self.__average_distance);
153
        
154
        self.__weights = [ [ 0.0 for _ in range(len(stimulus)) ] for _ in range(len(stimulus)) ];
155
        self.__weights_summary = [ 0.0 for _ in range(self.__num_osc) ];
156
        
157
        if (self.__conn_type == type_conn.ALL_TO_ALL):
158
            self.__create_weights_all_to_all(stimulus);
159
        
160
        elif (self.__conn_type == type_conn.TRIANGULATION_DELAUNAY):
161
            self.__create_weights_delaunay_triangulation(stimulus);
162
    
163
    
164
    def __create_weights_all_to_all(self, stimulus):
165
        for i in range(len(stimulus)):
166
            for j in range(i + 1, len(stimulus)):
167
                weight = self.__calculate_weight(stimulus[i], stimulus[j]);
168
                print(i, j, weight, stimulus[i], stimulus[j]);
169
                
170
                self.__weights[i][j] = weight;
171
                self.__weights[j][i] = weight;
172
                
173
                self.__weights_summary[i] += weight;
174
                self.__weights_summary[j] += weight;
175
    
176
    
177
    def __create_weights_delaunay_triangulation(self, stimulus):
178
        pass;
179
    
180
    
181
    def __calculate_weight(self, oscillator_location1, oscillator_location2):
182
        distance = euclidean_distance_sqrt(oscillator_location1, oscillator_location2);
183
        return math.exp(-distance / (2.0 * self.__average_distance));
184