wolffd@0
|
1 function Ud = som_unit_dists(topol,lattice,shape)
|
wolffd@0
|
2
|
wolffd@0
|
3 %SOM_UNIT_DISTS Distances between unit-locations on the map grid.
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % Ud = som_unit_dists(topol,[lattice],[shape])
|
wolffd@0
|
6 %
|
wolffd@0
|
7 % Ud = som_unit_dists(sMap);
|
wolffd@0
|
8 % Ud = som_unit_dists(sMap.topol);
|
wolffd@0
|
9 % Ud = som_unit_dists(msize, 'hexa', 'cyl');
|
wolffd@0
|
10 % Ud = som_unit_dists([10 4 4], 'rect', 'toroid');
|
wolffd@0
|
11 %
|
wolffd@0
|
12 % Input and output arguments ([]'s are optional):
|
wolffd@0
|
13 % topol topology of the SOM grid
|
wolffd@0
|
14 % (struct) topology or map struct
|
wolffd@0
|
15 % (vector) the 'msize' field of topology struct
|
wolffd@0
|
16 % [lattice] (string) map lattice, 'rect' by default
|
wolffd@0
|
17 % [shape] (string) map shape, 'sheet' by default
|
wolffd@0
|
18 %
|
wolffd@0
|
19 % Ud (matrix, size [munits munits]) distance from each map unit
|
wolffd@0
|
20 % to each map unit
|
wolffd@0
|
21 %
|
wolffd@0
|
22 % For more help, try 'type som_unit_dists' or check out online documentation.
|
wolffd@0
|
23 % See also SOM_UNIT_COORDS, SOM_UNIT_NEIGHS.
|
wolffd@0
|
24
|
wolffd@0
|
25 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
26 %
|
wolffd@0
|
27 % som_unit_dists
|
wolffd@0
|
28 %
|
wolffd@0
|
29 % PURPOSE
|
wolffd@0
|
30 %
|
wolffd@0
|
31 % Returns interunit distances between the units of a Self-Organizing Map
|
wolffd@0
|
32 % along the map grid.
|
wolffd@0
|
33 %
|
wolffd@0
|
34 % SYNTAX
|
wolffd@0
|
35 %
|
wolffd@0
|
36 % Ud = som_unit_dists(sTopol);
|
wolffd@0
|
37 % Ud = som_unit_dists(sM.topol);
|
wolffd@0
|
38 % Ud = som_unit_dists(msize);
|
wolffd@0
|
39 % Ud = som_unit_dists(msize,'hexa');
|
wolffd@0
|
40 % Ud = som_unit_dists(msize,'rect','toroid');
|
wolffd@0
|
41 %
|
wolffd@0
|
42 % DESCRIPTION
|
wolffd@0
|
43 %
|
wolffd@0
|
44 % Calculates the distances between the units of a SOM based on the
|
wolffd@0
|
45 % given topology. The distance are euclidian and they are measured
|
wolffd@0
|
46 % along the map grid (in the output space).
|
wolffd@0
|
47 %
|
wolffd@0
|
48 % In case of 'sheet' shape, the distances can be measured directly
|
wolffd@0
|
49 % from the unit coordinates given by SOM_UNIT_COORDS.
|
wolffd@0
|
50 %
|
wolffd@0
|
51 % In case of 'cyl' and 'toroid' shapes this is not so. In these cases
|
wolffd@0
|
52 % the coordinates are calculated as in the case of 'sheet' shape and
|
wolffd@0
|
53 % the shape is then taken into account by shifting the map grid into
|
wolffd@0
|
54 % different positions.
|
wolffd@0
|
55 %
|
wolffd@0
|
56 % Consider, for example, a 4x3 map. The basic position of map units
|
wolffd@0
|
57 % is shown on the left (with '1' - 'C' each denoting one map unit).
|
wolffd@0
|
58 % In case of a 'cyl' shape, units on the left and right edges are
|
wolffd@0
|
59 % neighbors, so for this purpose the map is copied on the left and
|
wolffd@0
|
60 % right sides of the map, as on right.
|
wolffd@0
|
61 %
|
wolffd@0
|
62 % basic left basic right
|
wolffd@0
|
63 % ------- ------- ------- -------
|
wolffd@0
|
64 % 1 5 9 1 5 9 1 5 9 1 5 9
|
wolffd@0
|
65 % 2 6 a 2 6 a 2 6 a 2 6 a
|
wolffd@0
|
66 % 3 7 b 3 7 b 3 7 b 3 7 b
|
wolffd@0
|
67 % 4 8 c 4 8 c 4 8 c 4 8 c
|
wolffd@0
|
68 %
|
wolffd@0
|
69 % For the 'toroid' shape a similar trick is done, except that the
|
wolffd@0
|
70 % copies are placed all around the basic position:
|
wolffd@0
|
71 %
|
wolffd@0
|
72 % 1 5 9 1 5 9 1 5 9
|
wolffd@0
|
73 % 2 6 a 2 6 a 2 6 a
|
wolffd@0
|
74 % 3 7 b 3 7 b 3 7 b
|
wolffd@0
|
75 % 4 8 c 4 8 c 4 8 c
|
wolffd@0
|
76 % 1 5 9 1 5 9 1 5 9
|
wolffd@0
|
77 % 2 6 a 2 6 a 2 6 a
|
wolffd@0
|
78 % 3 7 b 3 7 b 3 7 b
|
wolffd@0
|
79 % 4 8 c 4 8 c 4 8 c
|
wolffd@0
|
80 % 1 5 9 1 5 9 1 5 9
|
wolffd@0
|
81 % 2 6 a 2 6 a 2 6 a
|
wolffd@0
|
82 % 3 7 b 3 7 b 3 7 b
|
wolffd@0
|
83 % 4 8 c 4 8 c 4 8 c
|
wolffd@0
|
84 %
|
wolffd@0
|
85 % From this we can see that the distance from unit '1' is 1 to units
|
wolffd@0
|
86 % '9','2','4' and '5', and sqrt(2) to units 'C','A','8' and '6'. Notice
|
wolffd@0
|
87 % that in the case of a 'hexa' lattice and 'toroid' shape, the size
|
wolffd@0
|
88 % of the map in y-direction should be even. The reason can be clearly
|
wolffd@0
|
89 % seen from the two figures below. On the left the basic positions for
|
wolffd@0
|
90 % a 3x3 map. If the map is copied above itself, it can be seen that the
|
wolffd@0
|
91 % lattice is broken (on the right):
|
wolffd@0
|
92 %
|
wolffd@0
|
93 % basic positions example of broken lattice
|
wolffd@0
|
94 % --------------- -------------------------
|
wolffd@0
|
95 % 1 4 7
|
wolffd@0
|
96 % 2 5 8
|
wolffd@0
|
97 % 3 6 9
|
wolffd@0
|
98 % 1 4 7 1 4 7
|
wolffd@0
|
99 % 2 5 8 2 5 8
|
wolffd@0
|
100 % 3 6 9 3 6 9
|
wolffd@0
|
101 %
|
wolffd@0
|
102 %
|
wolffd@0
|
103 % REQUIRED INPUT ARGUMENTS
|
wolffd@0
|
104 %
|
wolffd@0
|
105 % topol Map grid dimensions.
|
wolffd@0
|
106 % (struct) topology struct or map struct, the topology
|
wolffd@0
|
107 % (msize, lattice, shape) of the map is taken from
|
wolffd@0
|
108 % the appropriate fields (see e.g. SOM_SET)
|
wolffd@0
|
109 % (vector) the vector which gives the size of the map grid
|
wolffd@0
|
110 % (msize-field of the topology struct).
|
wolffd@0
|
111 %
|
wolffd@0
|
112 % OPTIONAL INPUT ARGUMENTS
|
wolffd@0
|
113 %
|
wolffd@0
|
114 % lattice (string) The map lattice, either 'rect' or 'hexa'. Default
|
wolffd@0
|
115 % is 'rect'. 'hexa' can only be used with 1- or
|
wolffd@0
|
116 % 2-dimensional map grids.
|
wolffd@0
|
117 % shape (string) The map shape, either 'sheet', 'cyl' or 'toroid'.
|
wolffd@0
|
118 % Default is 'sheet'.
|
wolffd@0
|
119 %
|
wolffd@0
|
120 % OUTPUT ARGUMENTS
|
wolffd@0
|
121 %
|
wolffd@0
|
122 % Ud (matrix) distances from each map unit to each other map unit,
|
wolffd@0
|
123 % size is [munits munits]
|
wolffd@0
|
124 %
|
wolffd@0
|
125 % EXAMPLES
|
wolffd@0
|
126 %
|
wolffd@0
|
127 % Simplest case:
|
wolffd@0
|
128 % Ud = som_unit_dists(sTopol);
|
wolffd@0
|
129 % Ud = som_unit_dists(sMap.topol);
|
wolffd@0
|
130 % Ud = som_unit_dists(msize);
|
wolffd@0
|
131 % Ud = som_unit_dists([10 10]);
|
wolffd@0
|
132 %
|
wolffd@0
|
133 % If topology is given as vector, lattice is 'rect' and shape is 'sheet'
|
wolffd@0
|
134 % by default. To change these, you can use the optional arguments:
|
wolffd@0
|
135 % Ud = som_unit_dists(msize, 'hexa', 'toroid');
|
wolffd@0
|
136 %
|
wolffd@0
|
137 % The distances can also be calculated for high-dimensional grids:
|
wolffd@0
|
138 % Ud = som_unit_dists([4 4 4 4 4 4]);
|
wolffd@0
|
139 %
|
wolffd@0
|
140 % SEE ALSO
|
wolffd@0
|
141 %
|
wolffd@0
|
142 % som_unit_coords Calculate grid coordinates.
|
wolffd@0
|
143 % som_unit_neighs Calculate neighborhoods of map units.
|
wolffd@0
|
144
|
wolffd@0
|
145 % Copyright (c) 1997-2000 by the SOM toolbox programming team.
|
wolffd@0
|
146 % http://www.cis.hut.fi/projects/somtoolbox/
|
wolffd@0
|
147
|
wolffd@0
|
148 % Version 1.0beta juuso 110997
|
wolffd@0
|
149 % Version 2.0beta juuso 101199 170400 070600 130600
|
wolffd@0
|
150
|
wolffd@0
|
151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
152 %% Check arguments
|
wolffd@0
|
153
|
wolffd@0
|
154 error(nargchk(1, 3, nargin));
|
wolffd@0
|
155
|
wolffd@0
|
156 % default values
|
wolffd@0
|
157 sTopol = som_set('som_topol','lattice','rect');
|
wolffd@0
|
158
|
wolffd@0
|
159 % topol
|
wolffd@0
|
160 if isstruct(topol),
|
wolffd@0
|
161 switch topol.type,
|
wolffd@0
|
162 case 'som_map', sTopol = topol.topol;
|
wolffd@0
|
163 case 'som_topol', sTopol = topol;
|
wolffd@0
|
164 end
|
wolffd@0
|
165 elseif iscell(topol),
|
wolffd@0
|
166 for i=1:length(topol),
|
wolffd@0
|
167 if isnumeric(topol{i}), sTopol.msize = topol{i};
|
wolffd@0
|
168 elseif ischar(topol{i}),
|
wolffd@0
|
169 switch topol{i},
|
wolffd@0
|
170 case {'rect','hexa'}, sTopol.lattice = topol{i};
|
wolffd@0
|
171 case {'sheet','cyl','toroid'}, sTopol.shape = topol{i};
|
wolffd@0
|
172 end
|
wolffd@0
|
173 end
|
wolffd@0
|
174 end
|
wolffd@0
|
175 else
|
wolffd@0
|
176 sTopol.msize = topol;
|
wolffd@0
|
177 end
|
wolffd@0
|
178 if prod(sTopol.msize)==0, error('Map size is 0.'); end
|
wolffd@0
|
179
|
wolffd@0
|
180 % lattice
|
wolffd@0
|
181 if nargin>1 & ~isempty(lattice) & ~isnan(lattice), sTopol.lattice = lattice; end
|
wolffd@0
|
182
|
wolffd@0
|
183 % shape
|
wolffd@0
|
184 if nargin>2 & ~isempty(shape) & ~isnan(shape), sTopol.shape = shape; end
|
wolffd@0
|
185
|
wolffd@0
|
186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
187 %% Action
|
wolffd@0
|
188
|
wolffd@0
|
189 msize = sTopol.msize;
|
wolffd@0
|
190 lattice = sTopol.lattice;
|
wolffd@0
|
191 shape = sTopol.shape;
|
wolffd@0
|
192
|
wolffd@0
|
193 munits = prod(msize);
|
wolffd@0
|
194 Ud = zeros(munits,munits);
|
wolffd@0
|
195
|
wolffd@0
|
196 % free topology
|
wolffd@0
|
197 if strcmp(lattice,'free'),
|
wolffd@0
|
198 N1 = sTopol.connection;
|
wolffd@0
|
199 Ud = som_neighborhood(N1,Inf);
|
wolffd@0
|
200 end
|
wolffd@0
|
201
|
wolffd@0
|
202 % coordinates of map units when the grid is spread on a plane
|
wolffd@0
|
203 Coords = som_unit_coords(msize,lattice,'sheet');
|
wolffd@0
|
204
|
wolffd@0
|
205 % width and height of the grid
|
wolffd@0
|
206 dx = max(Coords(:,1))-min(Coords(:,1));
|
wolffd@0
|
207 if msize(1)>1, dx = dx*msize(1)/(msize(1)-1); else dx = dx+1; end
|
wolffd@0
|
208 dy = max(Coords(:,2))-min(Coords(:,2));
|
wolffd@0
|
209 if msize(2)>1, dy = dy*msize(2)/(msize(2)-1); else dy = dy+1; end
|
wolffd@0
|
210
|
wolffd@0
|
211 % calculate distance from each location to each other location
|
wolffd@0
|
212 switch shape,
|
wolffd@0
|
213 case 'sheet',
|
wolffd@0
|
214 for i=1:(munits-1),
|
wolffd@0
|
215 inds = [(i+1):munits];
|
wolffd@0
|
216 Dco = (Coords(inds,:) - Coords(ones(munits-i,1)*i,:))';
|
wolffd@0
|
217 Ud(i,inds) = sqrt(sum(Dco.^2));
|
wolffd@0
|
218 end
|
wolffd@0
|
219
|
wolffd@0
|
220 case 'cyl',
|
wolffd@0
|
221 for i=1:(munits-1),
|
wolffd@0
|
222 inds = [(i+1):munits];
|
wolffd@0
|
223 Dco = (Coords(inds,:) - Coords(ones(munits-i,1)*i,:))';
|
wolffd@0
|
224 dist = sum(Dco.^2);
|
wolffd@0
|
225 % The cylinder shape is taken into account by adding and substracting
|
wolffd@0
|
226 % the width of the map (dx) from the x-coordinate (ie. shifting the
|
wolffd@0
|
227 % map right and left).
|
wolffd@0
|
228 DcoS = Dco; DcoS(1,:) = DcoS(1,:) + dx; %East (x+dx)
|
wolffd@0
|
229 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
230 DcoS = Dco; DcoS(1,:) = DcoS(1,:) - dx; %West (x-dx)
|
wolffd@0
|
231 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
232 Ud(i,inds) = sqrt(dist);
|
wolffd@0
|
233 end
|
wolffd@0
|
234
|
wolffd@0
|
235 case 'toroid',
|
wolffd@0
|
236 for i=1:(munits-1),
|
wolffd@0
|
237 inds = [(i+1):munits];
|
wolffd@0
|
238 Dco = (Coords(inds,:) - Coords(ones(munits-i,1)*i,:))';
|
wolffd@0
|
239 dist = sum(Dco.^2);
|
wolffd@0
|
240 % The toroid shape is taken into account as the cylinder shape was
|
wolffd@0
|
241 % (see above), except that the map is shifted also vertically.
|
wolffd@0
|
242 DcoS = Dco; DcoS(1,:) = DcoS(1,:) + dx; %East (x+dx)
|
wolffd@0
|
243 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
244 DcoS = Dco; DcoS(1,:) = DcoS(1,:) - dx; %West (x+dx)
|
wolffd@0
|
245 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
246 DcoS = Dco; DcoS(2,:) = DcoS(2,:) + dy; %South (y+dy)
|
wolffd@0
|
247 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
248 DcoS = Dco; DcoS(2,:) = DcoS(2,:) - dy; %North (y-dy)
|
wolffd@0
|
249 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
250 DcoS = Dco; DcoS(1,:) = DcoS(1,:) + dx; DcoS(2,:) = DcoS(2,:) - dy; %NorthEast (x+dx, y-dy)
|
wolffd@0
|
251 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
252 DcoS = Dco; DcoS(1,:) = DcoS(1,:) + dx; DcoS(2,:) = DcoS(2,:) + dy; %SouthEast (x+dx, y+dy)
|
wolffd@0
|
253 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
254 DcoS = Dco; DcoS(1,:) = DcoS(1,:) - dx; DcoS(2,:) = DcoS(2,:) + dy; %SouthWest (x-dx, y+dy)
|
wolffd@0
|
255 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
256 DcoS = Dco; DcoS(1,:) = DcoS(1,:) - dx; DcoS(2,:) = DcoS(2,:) - dy; %NorthWest (x-dx, y-dy)
|
wolffd@0
|
257 dist = min(dist,sum(DcoS.^2));
|
wolffd@0
|
258 Ud(i,inds) = sqrt(dist);
|
wolffd@0
|
259 end
|
wolffd@0
|
260
|
wolffd@0
|
261 otherwise,
|
wolffd@0
|
262 error (['Unknown shape: ', shape]);
|
wolffd@0
|
263
|
wolffd@0
|
264 end
|
wolffd@0
|
265
|
wolffd@0
|
266 Ud = Ud + Ud';
|
wolffd@0
|
267
|
wolffd@0
|
268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|