module Combinatorics.TreeDepth ( treeDepth, treeDepthSeq, nodeDepth, nodeDegreeProb, nodeDegreeExpect, ) where {- Date: Mon, 18 Apr 2005 18:00:22 +0200 From: Daniel Beer <daniel.beer@informatik.tu-chemnitz.de> To: Hellseher <lemming@henning-thielemann.de> Subject: Baum-Stochastik Nimm folgenden Algorithmus, um einen zufälligen Baum mit n Knoten zu erzeugen: Starte mit einem einzelnen Knoten (=Wurzel) Schleife n-1 mal wähle beliebigen Knoten v1 aus Graph füge neuen Knoten v2 hinzu füge Kante (v1,v2) hinzu So jetzt die Fragen: a) Kann man den Erwartungswert für die Tiefe des Baums (also längster Pfad von Wurzel zu einem Blatt) berechnen? b) Kann man den Erwartungswert für die Anzahl der Blätter berechnen? c) Erweiterung von (b). Kann man die zu erwartende Verteilung der Ausgangsgrade berechnen (so eine Art Histogramm, das angibt wie oft welcher Ausgangsgrad erwartungsgemäß vorkommt)? Natürlich alles in Abhängigkeit von n versteht sich. -} import qualified Polynomial as Poly import qualified Data.Map as Map import Data.Ratio ((%), ) {- Instead of handling probabilities we make a complete case analysis and talk only about the absolute frequencies. That is we start with a one-node tree then create a new two-node tree from it. From (n-1)! n-node trees we create n! new (n+1)-node-trees. The expectation value of the depth of a node is the n-th harmonic number. -} {-| @nodeDepth !! n !! k@ is the absolute frequency of nodes with depth k in trees with n nodes. -} nodeDepth :: [[Integer]] nodeDepth = scanl (flip nodeDepthIt) [1] [1 ..] nodeDepthIt :: Integer -> [Integer] -> [Integer] nodeDepthIt n = Poly.mul [n,1] {-| @treeDepth !! n !! m !! k@ is the absolute frequency of nodes with depth k in trees with n nodes and depth m. This can't work - the function carries not enough information for recursive definition. treeDepth :: [[[Integer]]] treeDepth = iterate (\ls -> zipWith treeDepthIt ([[]]++ls) (ls++[[0]])) [[1]] treeDepthIt :: [Integer] -> [Integer] -> [Integer] treeDepthIt nm0 nm1 = foldl1 add [scale (if null nm0 then 0 else last nm0) (nm0 ++ [1]), scale (sum (init nm1)) nm1, 0 : init nm1] -} {-| Trees are abstracted to lists of integers, where each integer denotes the number of nodes in the corresponding depth of the tree. The number associated with each tree is the frequency of this kind of tree on random tree generation. -} type TreeFreq = Map.Map [Integer] Integer treeDepth :: [Rational] treeDepth = zipWith (%) (map (sum . map (\(xs,c) -> fromIntegral (length xs) * c) . Map.toList) treePrototypes) (scanl (*) 1 [1 ..]) treeDepthSeq :: [[Integer]] treeDepthSeq = let count = map snd . Map.toList . Map.fromListWith (+) . map (\(xs,c) -> (length xs, c)) . Map.toList in map count treePrototypes treePrototypes :: [TreeFreq] treePrototypes = iterate treeDepthIt (Map.singleton [1] 1) extendTree :: [Integer] -> [[Integer]] extendTree tree = tail (snd (foldr (\x (xs,ys) -> (x:xs, ((x+1):xs) : map (x:) ys)) ([],[]) tree)) ++ [tree ++ [1]] treeDepthIt :: TreeFreq -> TreeFreq treeDepthIt fm = Map.fromListWith (+) (concatMap (\(xs,c) -> zip (extendTree xs) (map (c*) xs)) (Map.toList fm)) {-| @nodeDegree !! n !! k@ is the number of nodes with outdegree k in a n-node tree. -} nodeDegreeProb :: [[Rational]] nodeDegreeProb = zipWith (\den -> map (%den)) (scanl1 (*) [1 ..]) nodeDegree nodeDegree :: [[Integer]] nodeDegree = scanl (flip (uncurry nodeDegreeIt)) [1] (zip [0 ..] (scanl1 (*) [1 ..])) nodeDegreeIt :: Integer -> Integer -> [Integer] -> [Integer] nodeDegreeIt n nFac = Poly.add [nFac] . Poly.mul [n,1] {-| expected value of node degree -} nodeDegreeExpect :: [Rational] nodeDegreeExpect = zipWith (%) nodeDegreeExpectAux1 (scanl1 (*) [1 ..]) nodeDegreeExpectTrans :: Integer -> [Integer] -> [Integer] nodeDegreeExpectTrans s x = scanl (\acc (n,c) -> c + n*acc) s (zip [1 ..] x) nodeDegreeExpectAux0, nodeDegreeExpectAux1 :: [Integer] nodeDegreeExpectAux0 = nodeDegreeExpectTrans 1 (scanl1 (*) [1 ..]) nodeDegreeExpectAux1 = nodeDegreeExpectTrans 0 nodeDegreeExpectAux0