3 @brief Graph representation (uses format GRPR).
5 @authors Andrei Novikov (pyclustering@yandex.ru)
7 @copyright BSD-3-Clause
11 import matplotlib.pyplot
as plt
12 from matplotlib
import colors
14 from enum
import IntEnum
19 @brief Enumeration of graph description.
20 @details Matrix representation is list of lists where number of rows equals number of columns and each element
21 of square matrix determines whether there is connection between two vertices. For example:
22 [ [0, 1, 1], [1, 0, 1], [1, 1, 0] ].
24 Vector representation is list of lists where index of row corresponds to index of vertex and elements
25 of row consists of indexes of connected vertices. For example:
26 [ [1, 2], [0, 2], [0, 1] ].
34 GRAPH_MATRIX_DESCR = 1;
37 GRAPH_VECTOR_DESCR = 2;
42 @brief Graph representation.
46 def __init__(self, data, type_graph = None, space_descr = None, comments = None):
48 @brief Constructor of graph.
50 @param[in] data (list): Representation of graph. Considered as matrix if 'type_graph' is not specified.
51 @param[in] type_graph (type_graph_descr): Type of graph representation in 'data'.
52 @param[in] space_descr (list): Coordinates of each vertex that are used for graph drawing (can be omitted).
53 @param[in] comments (string): Comments related to graph.
60 if (type_graph
is not None):
65 if (len(row) != len(self.
__data)):
70 if ( (element != 0)
or (element != 1) ):
76 @return (uint) Size of graph defined by number of vertices.
85 @return (list) Graph representation.
93 @return (list) Space description.
104 @return (string) Comments.
112 @return (type_graph_descr) Type of graph representation.
120 @brief Read graph from file in GRPR format.
122 @param[in] filename (string): Path to file with graph in GRPR format.
124 @return (graph) Graph that is read from file.
128 file = open(filename,
'r');
135 map_data_repr = dict();
138 if (line[0] ==
'c' or line[0] ==
'p'):
139 comments += line[1:];
141 elif (line[0] ==
'r'):
142 node_coordinates = [float(val)
for val
in line[1:].split()];
143 if (len(node_coordinates) != 2):
144 raise NameError(
'Invalid format of space description for node (only 2-dimension space is supported)');
146 space_descr.append( [float(val)
for val
in line[1:].split()] );
148 elif (line[0] ==
'm'):
149 if ( (data_type
is not None)
and (data_type !=
'm') ):
150 raise NameError(
'Invalid format of graph representation (only one type should be used)');
153 data.append( [float(val)
for val
in line[1:].split()] );
155 elif (line[0] ==
'v'):
156 if ( (data_type
is not None)
and (data_type !=
'v') ):
157 raise NameError(
'Invalid format of graph representation (only one type should be used)');
160 data.append( [float(val)
for val
in line[1:].split()] );
162 elif (line[0] ==
'e'):
163 if ( (data_type
is not None)
and (data_type !=
'e') ):
164 raise NameError(
'Invalid format of graph representation (only one type should be used)');
167 vertices = [int(val)
for val
in line[1:].split()];
169 if (vertices[0]
not in map_data_repr):
170 map_data_repr[ vertices[0] ] = [ vertices[1] ];
172 map_data_repr[ vertices[0] ].append(vertices[1])
174 if (vertices[1]
not in map_data_repr):
175 map_data_repr[ vertices[1] ] = [ vertices[0] ];
177 map_data_repr[ vertices[1] ].append(vertices[0]);
180 elif (len(line.strip()) == 0):
continue;
184 raise NameError(
'Invalid format of file with graph description');
187 if (data_type ==
'e'):
188 for index
in range(len(map_data_repr)):
189 data.append([0] * len(map_data_repr));
191 for index_neighbour
in map_data_repr[index + 1]:
192 data[index][index_neighbour - 1] = 1;
198 if (data_type ==
'm'): graph_descr = type_graph_descr.GRAPH_MATRIX_DESCR;
199 elif (data_type ==
'v'): graph_descr = type_graph_descr.GRAPH_VECTOR_DESCR;
200 elif (data_type ==
'e'): graph_descr = type_graph_descr.GRAPH_MATRIX_DESCR;
202 raise NameError(
'Invalid format of file with graph description');
204 if (space_descr != []):
205 if (len(data) != len(space_descr)):
206 raise NameError(
"Invalid format of file with graph - number of nodes is different in space representation and graph description");
208 return graph(data, graph_descr, space_descr, comments);
216 @param[in] graph_instance (graph): Graph that should be drawn.
217 @param[in] map_coloring (list): List of color indexes for each vertex. Size of this list should be equal to size of graph (number of vertices).
218 If it's not specified (None) than graph without coloring will be dwarn.
220 @warning Graph can be represented if there is space representation for it.
224 if (graph_instance.space_description
is None):
225 raise NameError(
"The graph haven't got representation in space");
227 if (map_coloring
is not None):
228 if (len(graph_instance) != len(map_coloring)):
229 raise NameError(
"Size of graph should be equal to size coloring map");
233 axes = fig.add_subplot(111);
235 available_colors = [
'#00a2e8',
'#22b14c',
'#ed1c24',
236 '#fff200',
'#000000',
'#a349a4',
237 '#ffaec9',
'#7f7f7f',
'#b97a57',
238 '#c8bfe7',
'#880015',
'#ff7f27',
239 '#3f48cc',
'#c3c3c3',
'#ffc90e',
240 '#efe4b0',
'#b5e61d',
'#99d9ea',
241 '#7092b4',
'#ffffff'];
243 if (map_coloring
is not None):
244 if (len(map_coloring) > len(available_colors)):
245 raise NameError(
'Impossible to represent colored graph due to number of specified colors.');
247 x_maximum = -float(
'inf');
248 x_minimum = float(
'inf');
249 y_maximum = -float(
'inf');
250 y_minimum = float(
'inf');
252 for i
in range(0, len(graph_instance.space_description), 1):
253 if (graph_instance.type_graph_descr == type_graph_descr.GRAPH_MATRIX_DESCR):
254 for j
in range(i, len(graph_instance.space_description), 1):
255 if (graph_instance.data[i][j] == 1):
256 axes.plot([graph_instance.space_description[i][0], graph_instance.space_description[j][0]], [graph_instance.space_description[i][1], graph_instance.space_description[j][1]],
'k-', linewidth = 1.5);
258 elif (graph_instance.type_graph_descr == type_graph_descr.GRAPH_VECTOR_DESCR):
259 for j
in graph_instance.data[i]:
261 axes.plot([graph_instance.space_description[i][0], graph_instance.space_description[j][0]], [graph_instance.space_description[i][1], graph_instance.space_description[j][1]],
'k-', linewidth = 1.5);
264 if (map_coloring
is not None):
265 color_node = colors.hex2color(available_colors[map_coloring[i]]);
267 axes.plot(graph_instance.space_description[i][0], graph_instance.space_description[i][1], color = color_node, marker =
'o', markersize = 20);
269 if (x_maximum < graph_instance.space_description[i][0]): x_maximum = graph_instance.space_description[i][0];
270 if (x_minimum > graph_instance.space_description[i][0]): x_minimum = graph_instance.space_description[i][0];
271 if (y_maximum < graph_instance.space_description[i][1]): y_maximum = graph_instance.space_description[i][1];
272 if (y_minimum > graph_instance.space_description[i][1]): y_minimum = graph_instance.space_description[i][1];
274 plt.xlim(x_minimum - 0.5, x_maximum + 0.5);
275 plt.ylim(y_minimum - 0.5, y_maximum + 0.5);