@@ -238,20 +238,8 @@ trainStartSOM opts =
238238
239239runGen :: GenOpts -> IO (A. Matrix Float , [[Float ]], A. Matrix Float )
240240runGen opts = do
241- let somn = genX opts * genY opts
242- coords = (`divMod` genY opts)
243- somsqdist i j =
244- let (a, b) = coords i
245- (c, d) = coords j
246- in (a - c) * (a - c) + (b - d) * (b - d)
247- proj =
248- map
249- ((\ (a, b) -> [fromIntegral a, fromIntegral b]) . coords)
250- [0 .. somn - 1 ]
251- topo =
252- A. fromFunction
253- (Z :. somn :. somn)
254- (\ (Z :. i :. j) -> fromIntegral $ somsqdist i j)
241+ let (proj, topo) = genTopo (genShape opts)
242+ (Z :. somn :. _) = A. arrayShape topo
255243 centroids <-
256244 A. fromList (Z :. somn :. genDim opts)
257245 . fst
@@ -270,3 +258,72 @@ outputSSCStats opts sums sqsums counts = do
270258 J. encodeFile o $ A. toList counts
271259 withJust (statsVariancesOut opts) $ \ o -> do
272260 J. encodeFile o . matrixArray $ somVariancesLL sums sqsums counts
261+
262+ {-
263+ - Topology generators
264+ -}
265+ anglesAround :: (Floating a2 , Integral a1 ) => a1 -> [a2 ]
266+ anglesAround n = [2 * pi * fromIntegral i / fromIntegral n | i <- [0 .. pred n]]
267+
268+ sqAngleDist :: Floating a => a -> a -> a
269+ sqAngleDist a b = 1 - sin a * sin b - cos a * cos b
270+
271+ squared :: Num a => a -> a
272+ squared a = a * a
273+
274+ rng :: (Integral a , Num b ) => a -> [b ]
275+ rng e = fromIntegral <$> [0 .. pred e]
276+
277+ rng1 :: (Integral a , Num b ) => a -> [b ]
278+ rng1 e = fromIntegral <$> [1 .. pred e]
279+
280+ genTopo :: SomShape -> ([[Float ]], A. Matrix Float )
281+ genTopo (SomRectangle gx gy) = (proj, topo)
282+ where
283+ somn = gx * gy
284+ coords = (`divMod` gy)
285+ somsqdist i j =
286+ let (a, b) = coords i
287+ (c, d) = coords j
288+ in squared (a - c) + squared (b - d)
289+ proj =
290+ map
291+ ((\ (a, b) -> [fromIntegral a, fromIntegral b]) . coords)
292+ [0 .. somn - 1 ]
293+ topo =
294+ A. fromFunction
295+ (Z :. somn :. somn)
296+ (\ (Z :. i :. j) -> fromIntegral $ somsqdist i j)
297+ genTopo (SomHex hx hy hz) = (proj, arrayMatrix sqdists)
298+ where
299+ off1 = 0.5
300+ off2 = sqrt 3 / 2
301+ proj =
302+ [[x - off1 * y, off2 * y] | x <- rng hx, y <- rng hy]
303+ ++ [[x - off1 * z, - off2 * z] | x <- rng hx, z <- rng1 hz]
304+ ++ [[- off1 * (y + z), off2 * (y - z)] | y <- rng1 hy, z <- rng1 hz]
305+ sqdists = [map (sum . map squared . zipWith (-) a0) proj | a0 <- proj]
306+ genTopo (SomTorus tx ty) = (proj, arrayMatrix sqdists)
307+ where
308+ proj = [[x, y] | x <- rng tx, y <- rng ty]
309+ angles = [(a, b) | a <- anglesAround tx, b <- anglesAround ty]
310+ sqdists = do
311+ (a0, b0) <- angles
312+ pure $ do
313+ (a, b) <- angles
314+ pure
315+ $ fromIntegral tx * sqAngleDist a a0
316+ + fromIntegral ty * sqAngleDist b b0
317+ genTopo (SomCircle clen cwid) = (proj, arrayMatrix sqdists)
318+ where
319+ anglepos =
320+ [(a, fromIntegral x) | a <- anglesAround clen, x <- [0 .. pred cwid]]
321+ proj = do
322+ (a, x) <- anglepos
323+ let r = x + fromIntegral clen / (2 * pi )
324+ pure [cos a * r, sin a * r]
325+ sqdists = do
326+ (a0, x0) <- anglepos
327+ pure $ do
328+ (a, x) <- anglepos
329+ pure $ fromIntegral clen * sqAngleDist a a0 + squared (x - x0)
0 commit comments