Emping-0.2: src/CSVTable.hs
module CSVTable (rule2Attls,res2CSVTb,abd2CSVTb,amb2CSVTb ) where
-- (c) 2007 Hans van Thiel
-- Version 0.2 License GPL
-- module: convert reduction result to a CSV
-- format that can be read by Open Office Calc
import Data.Char (isDigit )
import Data.List ( delete )
import Data.Array
import Data.Tree ( Tree(..), Forest )
-- auxiliary functions
-- check whether a string is a number or text
allDigit :: String -> Bool
allDigit [] = True
allDigit (x:xs) | isDigit x = allDigit xs
| otherwise = False
-- convert string or number to OO Calc format
toCalc :: String -> String
toCalc x | allDigit x = x
| otherwise = "\"" ++ x ++ "\""
-- insert a separator s between two strings
inSep :: String -> String -> String -> String
inSep s x y = x ++ s ++ y
-- value string of an attribute-value tuple
av2ValStr :: Array Int [String] -> (Int,Int) -> String
av2ValStr attvarr (x,y) =
toCalc ((attvarr ! x) !! y)
-- get attribute string from index to array
a2AttStr :: Array Int [String] -> Int -> String
a2AttStr attvarr ix = head (attvarr ! ix)
-- lookup an av pair from an attribute
lkp :: Int -> [(Int,Int)] -> Maybe (Int,Int)
lkp att [] = Nothing
lkp att (x:xs) | att == fst x = Just x
| otherwise = lkp att xs
-- order a reduced rule to att list and fill in the blanks
formatRed :: [Int] -> [(Int,Int)] -> [Maybe (Int,Int)]
formatRed [] red = []
formatRed (x:xs) red = (lkp x red): (formatRed xs red)
-- transform a maybe av pair to a OO Calc string
mbAV2Calc :: Array Int [String] -> Maybe (Int,Int) -> String
mbAV2Calc attvarr avp =
case avp of
Just x -> av2ValStr attvarr x
Nothing -> " "
-- transform a reduced rule to a list of OOCalc strings
red2CalStr :: Array Int [String] -> [Int] -> [(Int,Int)] -> [String]
red2CalStr attvarr attls red =
map (mbAV2Calc attvarr) frmred where
frmred = formatRed attls red
-- convert a reduced rule to a .csv table row
red2CSV :: Array Int [String] -> [Int] -> [(Int,Int)] -> String
red2CSV attvarr attls red =
(foldr1 (inSep ",") (init calcs)) ++
",\" is \"," ++ (last calcs) ++ "\n" where
calcs = red2CalStr attvarr attls red
--------------------------------------------------
-- get the attributes from a rule (ORIGINAL RULE)
rule2Attls :: [(Int,Int)] -> [Int]
rule2Attls rule = map fst rule
----------------------------------------------------
-- convert header to .csv table row
hdr2CSV :: Array Int [String] -> [Int] -> String
hdr2CSV attvarr attls =
(foldr1 (inSep ",") (init calcs)) ++
", ," ++ (last calcs) ++ "\n" where
strls = map (a2AttStr attvarr) attls
calcs = map toCalc strls
--------------------------------------------------
-- convert a reduction for the same av consequent to .csv
sameCons2CSV :: Array Int [String] -> [Int] -> [[(Int,Int)]] -> String
sameCons2CSV attvarr attls redsame =
concatMap (red2CSV attvarr attls) redsame
-- convert a reductions for an attribute to .csv
allReds2CSV :: Array Int [String] -> [Int] -> [[[(Int,Int)]]] -> String
allReds2CSV attvarr attls redgrp =
concatMap (sameCons2CSV attvarr attls) redgrp
--------------------------------------------------
-- convert all reductions for an attribute to .csv table
res2CSVTb :: Array Int [String] -> [Int] -> [[[(Int,Int)]]] -> String
res2CSVTb attvarr attls redgrp =
(hdr2CSV attvarr attls) ++
allReds2CSV attvarr attls redgrp
----------------------------------------------------
----------------------------------------------------
-- section for .csv output of abductions
-- get the branches of a tree
brTree :: Tree a -> [[a]]
brTree (Node x []) = [[x]]
brTree (Node x for) = map (x:) brls where
brls = concatMap brTree for
-- show the antecedent as a .csv string
-- analogous to red2CSV, but on init, without consequent
ant2CSV :: Array Int [String] -> [Int] -> [(Int,Int)] -> String
ant2CSV attvarr attls red =
foldr1 (inSep ",") calcs where
calcs = red2CalStr attvarr (init attls) (init red)
-- show a list of equals in .csv format
eqs2CSV :: Array Int [String] -> [Int] -> [[(Int,Int)]] -> String
eqs2CSV attvarr attls eqls
| length eqls == 1 =
ant2CSV attvarr attls (head eqls)
| otherwise =
foldr1 (inSep ",\"equals\"\n") strls where
strls = map (ant2CSV attvarr attls) eqls
-- show a chain of equals in .csv format
chain2CSV :: Array Int [String] -> [Int] -> [[[(Int,Int)]]] -> String
chain2CSV attvarr attls chain
| length chain == 1 = eqs2CSV attvarr attls (head chain)
| otherwise = foldr1 (inSep ",\"implies\"\n") strls where
strls = map (eqs2CSV attvarr attls) chain
ruleChain2CSV :: Array Int [String] -> [Int] -> String -> [[[(Int,Int)]]] -> String
ruleChain2CSV attvarr attls cons chain =
(chain2CSV attvarr attls chain) ++
",\" is \"," ++ cons ++ "\n\n"
-------------------------------------------------------
-- get the consequent value string from a tree
consfrTree :: Array Int [String] -> Tree [[(Int,Int)]] -> String
consfrTree attvarr t =
av2ValStr attvarr cns where
cns = last (head (rootLabel t))
-- list of chains from a tree
-- Note: reverse all branches
chainsfrTree :: Tree [[(Int,Int)]] -> [[[[(Int,Int)]]]]
chainsfrTree t = map reverse (brTree t)
-- show a tree in .csv format
tree2CSV :: Array Int [String] -> [Int] -> Tree [[(Int,Int)]] -> String
tree2CSV attvarr attls t =
concatMap (ruleChain2CSV attvarr attls cons) chains where
chains = chainsfrTree t
cons = consfrTree attvarr t
---------------------------------------------------------
-- a forest of abduction trees to .csv format
forest2CSV :: Array Int [String] -> [Int] -> Forest [[(Int,Int)]] -> String
forest2CSV attvarr attls for =
concatMap (tree2CSV attvarr attls) for
-----------------------------------------------------
-- abduction result to .csv format
allAbds2CSV :: Array Int [String] -> [Int] -> [Forest [[(Int,Int)]] ]-> String
allAbds2CSV attvarr attls abdgrp =
concatMap (forest2CSV attvarr attls) abdgrp
----------------------------------------------------
-- abduction result to .csv table
abd2CSVTb :: Array Int [String] -> [Int] -> [Forest [[(Int,Int)]] ] -> String
abd2CSVTb attvarr attls abdgrp =
(hdr2CSV attvarr attls) ++
allAbds2CSV attvarr attls abdgrp
-----------------------------------------------------
-----------------------------------------------------
-- show ambiguous original rules in .csv format
-- Note: original rules do not need intermediate Maybe's
org2CSV :: Array Int [String] -> [(Int,Int)] -> String
org2CSV attvarr orule =
antstr ++ ",\" is \"," ++ constr ++ "\n" where
antstr = foldr1 (inSep ",") antstrls
antstrls = init rulestrls
constr = last rulestrls
rulestrls = map (av2ValStr attvarr) orule
-- ambiguous rules to .csv (always more than one)
ambs2CSV :: Array Int [String] -> [[(Int,Int)]] -> String
ambs2CSV attvarr ambrls =
(concatMap (org2CSV attvarr) ambrls) ++ "\n"
ambgrp2CSV :: Array Int [String] -> [[[(Int,Int)]]] -> String
ambgrp2CSV attvarr ambgrp
| length ambgrp == 1 = ambs2CSV attvarr (head ambgrp)
| otherwise = concatMap (ambs2CSV attvarr) ambgrp
amb2CSVTb :: Array Int [String] -> [Int] -> [[[(Int,Int)]]] -> String
amb2CSVTb attvarr attls ambgrp =
hdr2CSV attvarr attls ++ ambstr where
ambstr = ambgrp2CSV attvarr ambgrp