module DecisionTree where import IO import List data DecisionTree = Test String String String DecisionTree DecisionTree | Value String Double Double deriving (Show, Eq, Ord, Read) readDecisionTree :: String -> DecisionTree readDecisionTree s = let (_, wholeTree, subTrees) = readDecisionTree' False subTrees (filter (/=[]) (lines s)) in wholeTree readDecisionTree' :: Bool -> [(String,DecisionTree)] -> [String] -> ([String], DecisionTree, [(String,DecisionTree)]) readDecisionTree' _ subTrees [] = ([], Value "" 0 0, subTrees) readDecisionTree' areValue subTrees (x:xs) = let (lineDepth, lineType, values') = readLine x subTreesX = if xs /= [] && "Subtree" `isPrefixOf` head xs then readSubTrees subTrees xs else subTrees (xs', lhs, subTrees') = readDecisionTree' False subTreesX xs (xs'' , rhs, subTrees'') = readDecisionTree' False subTrees' xs' (xs''', other, subTrees''') = readDecisionTree' True subTreesX xs values = values' ++ ["0.0"] in if lineType -- are we a value then if areValue then (xs, Value (values !! 3) (read (values !! 4)) (read (values !! 5)), subTreesX) else (xs''', Test (values !! 0) (values !! 1) (values !! 2) (Value (values !! 3) (read (values !! 4)) (read (values !! 5))) other, subTrees''') else if '[' == head (last values') -- are we a subtree? then case lookup (last values') subTreesX of Nothing -> error "could not find subtree" Just dt -> (xs'', Test (values !! 0) (values !! 1) (values !! 2) dt lhs, subTrees') else (xs'', Test (values !! 0) (values !! 1) (values !! 2) lhs rhs, subTrees'') readSubTrees subTrees [] = subTrees readSubTrees subTrees (x:xs) | "Subtree" `isPrefixOf` x = let name = (words x) !! 1 treeDef = takeWhile (\x -> not ("Subtree" `isPrefixOf` x)) xs rest = dropWhile (\x -> not ("Subtree" `isPrefixOf` x)) xs (_, thisDT, _) = readDecisionTree' False subTrees treeDef in readSubTrees ((name,thisDT):subTrees) xs readLine :: String -> (Int,Bool,[String]) -- True = Value, False = Test readLine s = (length (elemIndices '|' s), ')' `elem` s, vals) where vals = words $ map (\x -> if x `elem` ":()/" then ' ' else x) $ dropWhile (`elem` "| ") s simpleDT = ["localDefCountSum <= 4 : p (101.0/6.0)", "localDefCountSum > 4 : u (7.0)"] simpleDT2 = [ "isArgument0 = t: u (33.0/1.4)", "isArgument0 = f:", "| isArgument1 = f: u (9.0/1.3)", "| isArgument1 = t:", "| | isRecursive1 = t: s (945.0/39.8)", "| | isRecursive1 = f: u (2.0/1.0)"] {- Test "isArgument0" "=" "t" (Value "u" 33.0 1.4) (Test "isArgument0" "=" "f" (Test "isArgument1" "=" "f" (Value "u" 9.0 1.3) (Test "isArgument1" "=" "t" (Test "isRecursive1" "=" "t" (Value "s" 945.0 39.8) (Value "u" 2.0 1.0)) (Value "" 0.0 0.0))) (Value "" 0.0 0.0)) -} simpleDT3 = [ "isArgument0 = t: u (33.0/1.4)", "isArgument0 = f:", "| isArgument1 = f :[S1]", "| isArgument1 = t:", "| | isRecursive1 = t: s (945.0/39.8)", "| | isRecursive1 = f: u (2.0/1.0)", "", "Subtree [S1]", "", "localDefCount <= 15 : u (281.0/1.4)", "localDefCount > 15 : s (139.0/11.8)"]