OcTree на Haskell
От: STilda  
Дата: 14.08.09 20:05
Оценка:
Доброго времени суток.
Взялся ради эксперимента сделать OcTree на haskell.
Но пока что не трехмерный случай а одномерный.
Идея в том, что если имеется список точек с координатами от 0 до 1, то мы его делим на две части, в первой части точки с координатой меньше 0.5, во второй — больше 0.5. Далее процесс повторяется, делим точки первой части еще на две (в одной координаты меньше 0.25 в другой больше 0.25), и вторую часть тоже делим на две (до 0.75 и после 0.75). И так впринципе "до бесконечности".

На Хаскеле удобно это сделать так как ленивые вычисления.

По дизайну естественно хочется разделить процесс генерации бесконечного дерева от процесса ограничения этого дерева. Ограничения могут быть разные: по глубине дерева, по количеству точек в интервале, по каким-то характеристикам этих точек, и так далее.

Но вот возникла проблема. При разделении списка С1 текущего уровня на два новых списка хочется чтобы С1 уже память не забирал.
Тоесть смотрю я что в списке С1 1000 точек и думаю, нет, нужно следующий уровень взять, опускаюсь ниже по дереву, и С1 отпускаю чтоб удалился. Так вот не удаляется. Не могу разобраться почему.

Задачу упростил до того что просто на этапе самой генерации дерева обрубаю пустые ветки.
Если без обрубания — память идет только на последний уровень дерева а промежуточные списки действительно удаляются походу.
Если ставлю проверку на пустой список — хранится все списки на всех уровнях.
( см строку с (*) в коде )
Почему так?

Помогите кто может

type Point a = a
type PointList a = [Point a]
data OcTree a = Node (PointList a,PointList a) [OcTree a] | Empty

leafs Empty = [[]]
leafs (Node (items1,items2) forest) = items1 : items2 : concat (map leafs forest)

main = do
    putStrLn $ "Begin"
    seed <- newStdGen
    let randomPoints = randomlist 1000000 seed `use` forceList
    let tree = chopByLevelNumber 15 . makeOcTree $ randomPoints
    let lastlevel = leafs $ tree
    let lastlevelCount = map length lastlevel
    putStrLn $ "  Last level len : " ++ show ( length lastlevel )
    putStrLn $ "  Last level lengths : " ++ show lastlevelCount    
    putStrLn $ "End"

randomlist :: Int -> StdGen -> [Double]
randomlist n = take n . randoms

--
-- utilites
--

forceList :: [a] -> ()
forceList [] = ()
forceList ((!a):as) = forceList as

use :: a -> (a -> ()) -> a
use expr strat = strat expr `seq` expr

--
-- procedures to create an OcTree
--
split2 param items = split2base items
  where split2base [] = ([],[])
        split2base (x:xs) | x < param = (x:s1,s2)
                          | otherwise = (s1,x:s2)
          where (s1,s2) = split2base xs 

makeOcTree :: RealFloat a => PointList a -> OcTree a
makeOcTree items = mkOcTree0 0.5 items
  where 
        mkOcTree0 :: RealFloat a => a -> PointList a -> OcTree a
        --(*) mkOcTree0 _ [] = Empty
        mkOcTree0 param items =  Node (items1,items2) [lt,rt] 
          where 
                (items1,items2) = split2 param items
                lt = mkOcTree0 (0.5*param) items1
                rt = mkOcTree0 (1.5*param) items2
                

--
-- procedures to chop OcTree
--

chopByLevelNumber :: Int -> OcTree a -> OcTree a
chopByLevelNumber _ Empty = Empty
chopByLevelNumber 0 (Node lst _) = Node lst [Empty,Empty]
chopByLevelNumber n (Node lst forest) = Node lst (map (chopByLevelNumber (n-1)) forest)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.