DecisionTree (empty) → 0.0
raw patch · 16 files changed
+1046/−0 lines, 16 filesdep +basedep +containerssetup-changedbinary-added
Dependencies added: base, containers
Files
- Data/DecisionTree.hs +134/−0
- DecisionTree.cabal +21/−0
- LICENSE +3/−0
- README +4/−0
- Setup.lhs +4/−0
- dist/doc/html/DecisionTree/Data-DecisionTree.html binary
- dist/doc/html/DecisionTree/DecisionTree.haddock binary
- dist/doc/html/DecisionTree/doc-index.html +150/−0
- dist/doc/html/DecisionTree/haddock-util.js +133/−0
- dist/doc/html/DecisionTree/haddock.css +267/−0
- dist/doc/html/DecisionTree/haskell_icon.gif binary
- dist/doc/html/DecisionTree/index.html +92/−0
- dist/doc/html/DecisionTree/minus.gif binary
- dist/doc/html/DecisionTree/plus.gif binary
- lgpl-3.0.txt +165/−0
- test.hs +73/−0
+ Data/DecisionTree.hs view
@@ -0,0 +1,134 @@+-- | This module provides a very simple implementation of a decisiontree. It is \"optimized\" for readability, not so much for performance. I doubt it can be used for real (=huge) datasets, but it should be ok for a couple of hundred (thousand?) items.+-- +-- You are encouraged to have a look at the source+-- +-- It is build (for now) using the ID3 algorithm (or at least something closely resembling that). That means the attributes you choose must have a finite set of possible values.+module Data.DecisionTree (+ build,+ decide,+ Datum(D, dName, attributes),+ PreLabeled,+ Attribute(A, aName, possibleValues),+ DecisionTree) where++import Data.Maybe (fromJust)+import Data.List hiding (partition)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Function (on)++type PreLabeled a b= (b, Datum a)++-- | The type for our DecisionTree+data DecisionTree a b= Leaf b -- ^ Leafs have labels+ | Node { + att ::Attribute a, -- ^ a node asks for this attribute+ child :: a -> (DecisionTree a b) -- ^ and has children which can be found with a value of the attribute+ }++-- | A Datum has Attributes+data Attribute a = A {+ aName :: String, -- ^ Attributes have a name+ possibleValues :: [a] -- ^ and a set of possible values+ } ++-- | Things we want to find labels for+data Datum a= D {+ dName :: String, -- ^ They have names+ attributes :: [(Attribute a,a)] -- ^ and attributes+ } deriving Show++instance (Show a, Show b) => Show (DecisionTree a b) where+ show x = showTree x ""++showTree :: (Show a, Show b) => DecisionTree a b -> ShowS+showTree (Leaf x) = shows x+showTree (Node att child) = ('<':).shows att.("|\n"++).showList [child a | a <- possibleValues att].('>':)++instance Eq (Attribute a) where+ (==) = (==) `on` aName+ +instance Show (Attribute a) where+ show = aName+ +-- | Build a DecisionTree from the given Trainingset+build :: (Ord a, Ord b) => [Attribute a] -> [PreLabeled a b] -> DecisionTree a b+build atts dataset = case inf of+ 0 -> Leaf dominantLabel -- even the best Attribute doesn't gain any information. We're done+ _ -> Node { + att = bAtt,+ child = safeLookup+ } + where+ (inf,bAtt) = bestAttribute dataset atts -- get the best attribute+ p = partition dataset bAtt -- use it to partition the set+ children = Map.map (build atts) p -- recursivly build the children+ dominantLabel = fst $ Map.findMax $ groupLabels (map label dataset) -- in case we are done, get the label+ safeLookup a= fromJust $ Map.lookup a children+ + +-- | Which value does this Datum have for the given Attribute?+getValue :: Datum a-> Attribute a -> a+getValue d att = fromJust $ lookup att (attributes d)++-- | Extract a label +label :: PreLabeled a b -> b+label = fst++-- | Decide which label belongs to this Datum+decide :: Eq a => DecisionTree a b -> Datum a -> b+decide (Leaf b) _ = b -- we reached a Leaf, done+decide (Node att child) d = decide (child v) d where -- we're in a node, walk down+ v = getValue d att+ +-- | Partitions the Dataset according to the possible values of the attribute+partition :: (Ord a) =>[PreLabeled a b] -> Attribute a -> Map a [PreLabeled a b]+partition set att= foldl (\m k -> Map.insertWith (++) k [] m) grouped (possibleValues att) where+ grouped = groupWith (flip getValue att.snd) (:[]) (++) set++-- | Computes the entropy of a Dataset+--+-- the Entropy is defined as: sum (p_i * log_2 p_i)+-- where p_i = |{ x | x has Label i}|/|Dataset|+entropy :: (Ord b) => [b] -> Double+entropy set= (-1)*( Map.fold help 0 $ groupLabels set )+ where + n = fromIntegral $ length set+ help s acc | s/=0 = let p = fromIntegral s / n in acc+p*log p/log 2+ help _ _ = error "entropy: we are not supposed to get p=0"++-- we want to count how many Data we have for each label. Thus we group it with 1 as +-- singleton value and add 1 whenever we find another Datum with the same label +groupLabels :: Ord b => [b] -> Map b Int +groupLabels = groupWith id (const (1::Int)) (const succ)++-- | How much information does this Attribute give us for the given Dataset+-- it is defined as +--+-- entropy(set) - sum p_i * entropy {dat_i | dat has value i for attribute a}+information :: (Ord b, Ord a) => [PreLabeled a b] -- ^ the data+ -> Attribute a -- ^ the Attribute + -> Double -- ^ the Information+information dat att= entropy (map label dat) - sum (zipWith (*) pi (map entropy ps)) where+ ps = map (map label) $ Map.elems $ partition dat att -- the partitions, we're only interested in the labels+ pi = map ((/ n).fromIntegral.length) ps -- the size of the partition/size dataset+ n = fromIntegral $ length dat+ +-- | Return the attribute which gives us greatest gain in information+bestAttribute :: (Ord b, Ord a) => [PreLabeled a b] -> [Attribute a] -> (Double,Attribute a)+bestAttribute dat = head.sortBy (compare `on` negatedInf).computeInformation where+ negatedInf (inf,_) = -inf+ computeInformation = map (\x -> (information dat x,x))++-- | groups a Dataset using a Map. According to #haskell \"efficient\" grouping needs Ord. I agree with that+groupWith :: Ord k => (a -> k) -- ^ how to extract a key from a Datum+ -> (a -> v) -- ^ how to make a Datum into a value for the map+ -> (v -> v -> v) -- ^ how to fuse two values (should we have > 1 Data for this key)+ -> [a] -- ^ the list we want to group+ -> Map k v +groupWith getKey singleton fuse = + foldl (\m x -> Map.insertWith fuse (getKey x) (singleton x) m) Map.empty+ ++ +
+ DecisionTree.cabal view
@@ -0,0 +1,21 @@+Name: DecisionTree+Version: 0.0+Cabal-Version: >= 1.2+Synopsis: A very simple implementation of decision trees for discrete attributes.+Description: A very simple implementation of decision trees, built with ID3. You can use it to classify data with a set of discrete attributes.+License: LGPL+License-file: LICENSE+Author: Adrian Neumann+Homepage: http://page.mi.fu-berlin.de/~aneumann/decisiontree.html+Category: Algorithms, Pattern Classification+Maintainer: aneumann@inf.fu-berlin.de+stability: alpha+build-type: Simple+extra-source-files: README, test.hs, lgpl-3.0.txt++Library+ exposed-modules: Data.DecisionTree+ build-depends: + base, + containers >=0.2.0.0+ GHC-Options: -O2
+ LICENSE view
@@ -0,0 +1,3 @@+Copyright 2009 Adrian Neumann++You may use this library under the terms of the LGPL, which is included in the file lgpl-3.0.txt
+ README view
@@ -0,0 +1,4 @@+This is the DecisionTree library. +Build it as you would build any cabal package. Have a look at the Haskellwiki (haskell.org) if you don't know how.++Feel free to send me patches, comments, suggestions.
+ Setup.lhs view
@@ -0,0 +1,4 @@+#! /usr/bin/env runhaskell+ +> import Distribution.Simple+> main = defaultMain
+ dist/doc/html/DecisionTree/Data-DecisionTree.html view
binary file changed (absent → 20738 bytes)
+ dist/doc/html/DecisionTree/DecisionTree.haddock view
binary file changed (absent → 5224 bytes)
+ dist/doc/html/DecisionTree/doc-index.html view
@@ -0,0 +1,150 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>DecisionTree-0.0: A very simple implementation of decision trees for discrete attributes. (internal documentation) (Index)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock-util.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>DecisionTree-0.0: A very simple implementation of decision trees for discrete attributes. (internal documentation)</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD COLSPAN="2" STYLE="padding-top:5px;"+><FORM onsubmit="full_search(); return false;" ACTION=""+>Search: <INPUT ID="searchbox" onkeyup="quick_search()"+> <INPUT VALUE="Search" TYPE="submit"+> <SPAN ID="searchmsg"+> </SPAN+></FORM+></TD+></TR+><TR+><TD+><TABLE ID="indexlist" CELLPADDING="0" CELLSPACING="5"+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>A</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#v%3AA"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>aName</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#v%3AaName"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>Attribute</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#t%3AAttribute"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>attributes</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#v%3Aattributes"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>build</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#v%3Abuild"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>D</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#v%3AD"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>Datum</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#t%3ADatum"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>decide</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#v%3Adecide"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>DecisionTree</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#t%3ADecisionTree"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>dName</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#v%3AdName"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>possibleValues</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#v%3ApossibleValues"+>Data.DecisionTree</A+></TD+></TR+><TR CLASS="indexrow"+><TD CLASS="indexentry"+>PreLabeled</TD+><TD CLASS="indexlinks"+><A HREF="Data-DecisionTree.html#t%3APreLabeled"+>Data.DecisionTree</A+></TD+></TR+></TABLE+></TD+></TR+></TABLE+></BODY+></HTML+>
+ dist/doc/html/DecisionTree/haddock-util.js view
@@ -0,0 +1,133 @@+// Haddock JavaScript utilities+function toggle(button,id)+{+ var n = document.getElementById(id).style;+ if (n.display == "none")+ {+ button.src = "minus.gif";+ n.display = "block";+ }+ else+ {+ button.src = "plus.gif";+ n.display = "none";+ }+}+++var max_results = 75; // 50 is not enough to search for map in the base libraries+var shown_range = null;+var last_search = null;++function quick_search()+{+ perform_search(false);+}++function full_search()+{+ perform_search(true);+}+++function perform_search(full)+{+ var text = document.getElementById("searchbox").value.toLowerCase();+ if (text == last_search && !full) return;+ last_search = text;+ + var table = document.getElementById("indexlist");+ var status = document.getElementById("searchmsg");+ var children = table.firstChild.childNodes;+ + // first figure out the first node with the prefix+ var first = bisect(-1);+ var last = (first == -1 ? -1 : bisect(1));++ if (first == -1)+ {+ table.className = "";+ status.innerHTML = "No results found, displaying all";+ }+ else if (first == 0 && last == children.length - 1)+ {+ table.className = "";+ status.innerHTML = "";+ }+ else if (last - first >= max_results && !full)+ {+ table.className = "";+ status.innerHTML = "More than " + max_results + ", press Search to display";+ }+ else+ {+ // decide what you need to clear/show+ if (shown_range)+ setclass(shown_range[0], shown_range[1], "indexrow");+ setclass(first, last, "indexshow");+ shown_range = [first, last];+ table.className = "indexsearch";+ status.innerHTML = "";+ }++ + function setclass(first, last, status)+ {+ for (var i = first; i <= last; i++)+ {+ children[i].className = status;+ }+ }+ + + // do a binary search, treating 0 as ...+ // return either -1 (no 0's found) or location of most far match+ function bisect(dir)+ {+ var first = 0, finish = children.length - 1;+ var mid, success = false;++ while (finish - first > 3)+ {+ mid = Math.floor((finish + first) / 2);++ var i = checkitem(mid);+ if (i == 0) i = dir;+ if (i == -1)+ finish = mid;+ else+ first = mid;+ }+ var a = (dir == 1 ? first : finish);+ var b = (dir == 1 ? finish : first);+ for (var i = b; i != a - dir; i -= dir)+ {+ if (checkitem(i) == 0) return i;+ }+ return -1;+ } + + + // from an index, decide what the result is+ // 0 = match, -1 is lower, 1 is higher+ function checkitem(i)+ {+ var s = getitem(i).toLowerCase().substr(0, text.length);+ if (s == text) return 0;+ else return (s > text ? -1 : 1);+ }+ + + // from an index, get its string+ // this abstracts over alternates+ function getitem(i)+ {+ for ( ; i >= 0; i--)+ {+ var s = children[i].firstChild.firstChild.data;+ if (s.indexOf(' ') == -1)+ return s;+ }+ return ""; // should never be reached+ }+}
+ dist/doc/html/DecisionTree/haddock.css view
@@ -0,0 +1,267 @@+/* -------- Global things --------- */++BODY { + background-color: #ffffff;+ color: #000000;+ font-family: sans-serif;+ } ++A:link { color: #0000e0; text-decoration: none }+A:visited { color: #0000a0; text-decoration: none }+A:hover { background-color: #e0e0ff; text-decoration: none }++TABLE.vanilla {+ width: 100%;+ border-width: 0px;+ /* I can't seem to specify cellspacing or cellpadding properly using CSS... */+}++TABLE.vanilla2 {+ border-width: 0px;+}++/* <TT> font is a little too small in MSIE */+TT { font-size: 100%; }+PRE { font-size: 100%; }++LI P { margin: 0pt } ++TD {+ border-width: 0px;+}++TABLE.narrow {+ border-width: 0px;+}++TD.s8 { height: 8px; }+TD.s15 { height: 15px; }++SPAN.keyword { text-decoration: underline; }++/* Resize the buttom image to match the text size */+IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em }++/* --------- Contents page ---------- */++DIV.node {+ padding-left: 3em;+}++DIV.cnode {+ padding-left: 1.75em;+}++SPAN.pkg {+ position: absolute;+ left: 50em;+}++/* --------- Documentation elements ---------- */++TD.children {+ padding-left: 25px;+ }++TD.synopsis {+ padding: 2px;+ background-color: #f0f0f0;+ font-family: monospace+ }++TD.decl { + padding: 2px;+ background-color: #f0f0f0; + font-family: monospace;+ vertical-align: top;+ }++TD.topdecl {+ padding: 2px;+ background-color: #f0f0f0;+ font-family: monospace;+ vertical-align: top;+}++TABLE.declbar {+ border-spacing: 0px;+ }++TD.declname {+ width: 100%;+ }++TD.declbut {+ padding-left: 5px;+ padding-right: 5px;+ border-left-width: 1px;+ border-left-color: #000099;+ border-left-style: solid;+ white-space: nowrap;+ font-size: small;+ }++/* + arg is just like decl, except that wrapping is not allowed. It is+ used for function and constructor arguments which have a text box+ to the right, where if wrapping is allowed the text box squashes up+ the declaration by wrapping it.+*/+TD.arg { + padding: 2px;+ background-color: #f0f0f0; + font-family: monospace;+ vertical-align: top;+ white-space: nowrap;+ }++TD.recfield { padding-left: 20px }++TD.doc { + padding-top: 2px;+ padding-left: 10px;+ }++TD.ndoc { + padding: 2px;+ }++TD.rdoc { + padding: 2px;+ padding-left: 10px;+ width: 100%;+ }++TD.body { + padding-left: 10px+ }++TD.pkg {+ width: 100%;+ padding-left: 10px+}++TABLE.indexsearch TR.indexrow {+ display: none;+}+TABLE.indexsearch TR.indexshow {+ display: table-row;+}++TD.indexentry {+ vertical-align: top;+ padding-right: 10px+ }++TD.indexannot {+ vertical-align: top;+ padding-left: 20px;+ white-space: nowrap+ }++TD.indexlinks {+ width: 100%+ }++/* ------- Section Headings ------- */++TD.section1 {+ padding-top: 15px;+ font-weight: bold;+ font-size: 150%+ }++TD.section2 {+ padding-top: 10px;+ font-weight: bold;+ font-size: 130%+ }++TD.section3 {+ padding-top: 5px;+ font-weight: bold;+ font-size: 110%+ }++TD.section4 {+ font-weight: bold;+ font-size: 100%+ }++/* -------------- The title bar at the top of the page */++TD.infohead {+ color: #ffffff;+ font-weight: bold;+ padding-right: 10px;+ text-align: left;+}++TD.infoval {+ color: #ffffff;+ padding-right: 10px;+ text-align: left;+}++TD.topbar {+ background-color: #000099;+ padding: 5px;+}++TD.title {+ color: #ffffff;+ padding-left: 10px;+ width: 100%+ }++TD.topbut {+ padding-left: 5px;+ padding-right: 5px;+ border-left-width: 1px;+ border-left-color: #ffffff;+ border-left-style: solid;+ white-space: nowrap;+ }++TD.topbut A:link {+ color: #ffffff+ }++TD.topbut A:visited {+ color: #ffff00+ }++TD.topbut A:hover {+ background-color: #6060ff;+ }++TD.topbut:hover {+ background-color: #6060ff+ }++TD.modulebar { + background-color: #0077dd;+ padding: 5px;+ border-top-width: 1px;+ border-top-color: #ffffff;+ border-top-style: solid;+ }++/* --------- The page footer --------- */++TD.botbar {+ background-color: #000099;+ color: #ffffff;+ padding: 5px+ }+TD.botbar A:link {+ color: #ffffff;+ text-decoration: underline+ }+TD.botbar A:visited {+ color: #ffff00+ }+TD.botbar A:hover {+ background-color: #6060ff+ }+
+ dist/doc/html/DecisionTree/haskell_icon.gif view
binary file changed (absent → 911 bytes)
+ dist/doc/html/DecisionTree/index.html view
@@ -0,0 +1,92 @@+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">+<!--Rendered using the Haskell Html Library v0.2-->+<HTML+><HEAD+><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"+><TITLE+>DecisionTree-0.0: A very simple implementation of decision trees for discrete attributes. (internal documentation)</TITLE+><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css"+><SCRIPT SRC="haddock-util.js" TYPE="text/javascript"+></SCRIPT+></HEAD+><BODY+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD CLASS="topbar"+><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0"+><TR+><TD+><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" "+></TD+><TD CLASS="title"+>DecisionTree-0.0: A very simple implementation of decision trees for discrete attributes. (internal documentation)</TD+><TD CLASS="topbut"+><A HREF="index.html"+>Contents</A+></TD+><TD CLASS="topbut"+><A HREF="doc-index.html"+>Index</A+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="section1"+>DecisionTree-0.0: A very simple implementation of decision trees for discrete attributes. (internal documentation)</TD+></TR+><TR+><TD CLASS="doc"+>A very simple implementation of decision trees, built with ID3. You can use it to classify data with a set of discrete attributes.+</TD+></TR+><TR+><TD CLASS="section1"+>Modules</TD+></TR+><TR+><TD+><TABLE CLASS="vanilla2" CELLSPACING="0" CELLPADDING="0"+><TR+><TD STYLE="width: 50em"+><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'n:0')" ALT="show/hide"+>Data</TD+><TD+></TD+><TD+></TD+></TR+><TR+><TD STYLE="padding: 0; padding-left: 2em" COLSPAN="3"+><TABLE CLASS="vanilla2" CELLSPACING="0" CELLPADDING="0" ID="n:0" STYLE="display:block;"+><TR+><TD STYLE="padding-left: 1.25em;width: 48em"+><A HREF="Data-DecisionTree.html"+>Data.DecisionTree</A+></TD+><TD+></TD+><TD+></TD+></TR+></TABLE+></TD+></TR+></TABLE+></TD+></TR+><TR+><TD CLASS="s15"+></TD+></TR+><TR+><TD CLASS="botbar"+>Produced by <A HREF="http://www.haskell.org/haddock/"+>Haddock</A+> version 2.3.0</TD+></TR+></TABLE+></BODY+></HTML+>
+ dist/doc/html/DecisionTree/minus.gif view
binary file changed (absent → 56 bytes)
+ dist/doc/html/DecisionTree/plus.gif view
binary file changed (absent → 59 bytes)
+ lgpl-3.0.txt view
@@ -0,0 +1,165 @@+ GNU LESSER GENERAL PUBLIC LICENSE+ Version 3, 29 June 2007++ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.+++ This version of the GNU Lesser General Public License incorporates+the terms and conditions of version 3 of the GNU General Public+License, supplemented by the additional permissions listed below.++ 0. Additional Definitions. ++ As used herein, "this License" refers to version 3 of the GNU Lesser+General Public License, and the "GNU GPL" refers to version 3 of the GNU+General Public License.++ "The Library" refers to a covered work governed by this License,+other than an Application or a Combined Work as defined below.++ An "Application" is any work that makes use of an interface provided+by the Library, but which is not otherwise based on the Library.+Defining a subclass of a class defined by the Library is deemed a mode+of using an interface provided by the Library.++ A "Combined Work" is a work produced by combining or linking an+Application with the Library. The particular version of the Library+with which the Combined Work was made is also called the "Linked+Version".++ The "Minimal Corresponding Source" for a Combined Work means the+Corresponding Source for the Combined Work, excluding any source code+for portions of the Combined Work that, considered in isolation, are+based on the Application, and not on the Linked Version.++ The "Corresponding Application Code" for a Combined Work means the+object code and/or source code for the Application, including any data+and utility programs needed for reproducing the Combined Work from the+Application, but excluding the System Libraries of the Combined Work.++ 1. Exception to Section 3 of the GNU GPL.++ You may convey a covered work under sections 3 and 4 of this License+without being bound by section 3 of the GNU GPL.++ 2. Conveying Modified Versions.++ If you modify a copy of the Library, and, in your modifications, a+facility refers to a function or data to be supplied by an Application+that uses the facility (other than as an argument passed when the+facility is invoked), then you may convey a copy of the modified+version:++ a) under this License, provided that you make a good faith effort to+ ensure that, in the event an Application does not supply the+ function or data, the facility still operates, and performs+ whatever part of its purpose remains meaningful, or++ b) under the GNU GPL, with none of the additional permissions of+ this License applicable to that copy.++ 3. Object Code Incorporating Material from Library Header Files.++ The object code form of an Application may incorporate material from+a header file that is part of the Library. You may convey such object+code under terms of your choice, provided that, if the incorporated+material is not limited to numerical parameters, data structure+layouts and accessors, or small macros, inline functions and templates+(ten or fewer lines in length), you do both of the following:++ a) Give prominent notice with each copy of the object code that the+ Library is used in it and that the Library and its use are+ covered by this License.++ b) Accompany the object code with a copy of the GNU GPL and this license+ document.++ 4. Combined Works.++ You may convey a Combined Work under terms of your choice that,+taken together, effectively do not restrict modification of the+portions of the Library contained in the Combined Work and reverse+engineering for debugging such modifications, if you also do each of+the following:++ a) Give prominent notice with each copy of the Combined Work that+ the Library is used in it and that the Library and its use are+ covered by this License.++ b) Accompany the Combined Work with a copy of the GNU GPL and this license+ document.++ c) For a Combined Work that displays copyright notices during+ execution, include the copyright notice for the Library among+ these notices, as well as a reference directing the user to the+ copies of the GNU GPL and this license document.++ d) Do one of the following:++ 0) Convey the Minimal Corresponding Source under the terms of this+ License, and the Corresponding Application Code in a form+ suitable for, and under terms that permit, the user to+ recombine or relink the Application with a modified version of+ the Linked Version to produce a modified Combined Work, in the+ manner specified by section 6 of the GNU GPL for conveying+ Corresponding Source.++ 1) Use a suitable shared library mechanism for linking with the+ Library. A suitable mechanism is one that (a) uses at run time+ a copy of the Library already present on the user's computer+ system, and (b) will operate properly with a modified version+ of the Library that is interface-compatible with the Linked+ Version. ++ e) Provide Installation Information, but only if you would otherwise+ be required to provide such information under section 6 of the+ GNU GPL, and only to the extent that such information is+ necessary to install and execute a modified version of the+ Combined Work produced by recombining or relinking the+ Application with a modified version of the Linked Version. (If+ you use option 4d0, the Installation Information must accompany+ the Minimal Corresponding Source and Corresponding Application+ Code. If you use option 4d1, you must provide the Installation+ Information in the manner specified by section 6 of the GNU GPL+ for conveying Corresponding Source.)++ 5. Combined Libraries.++ You may place library facilities that are a work based on the+Library side by side in a single library together with other library+facilities that are not Applications and are not covered by this+License, and convey such a combined library under terms of your+choice, if you do both of the following:++ a) Accompany the combined library with a copy of the same work based+ on the Library, uncombined with any other library facilities,+ conveyed under the terms of this License.++ b) Give prominent notice with the combined library that part of it+ is a work based on the Library, and explaining where to find the+ accompanying uncombined form of the same work.++ 6. Revised Versions of the GNU Lesser General Public License.++ The Free Software Foundation may publish revised and/or new versions+of the GNU Lesser General Public License from time to time. Such new+versions will be similar in spirit to the present version, but may+differ in detail to address new problems or concerns.++ Each version is given a distinguishing version number. If the+Library as you received it specifies that a certain numbered version+of the GNU Lesser General Public License "or any later version"+applies to it, you have the option of following the terms and+conditions either of that published version or of any later version+published by the Free Software Foundation. If the Library as you+received it does not specify a version number of the GNU Lesser+General Public License, you may choose any version of the GNU Lesser+General Public License ever published by the Free Software Foundation.++ If the Library as you received it specifies that a proxy can decide+whether future versions of the GNU Lesser General Public License shall+apply, that proxy's public statement of acceptance of any version is+permanent authorization for you to choose that version for the+Library.
+ test.hs view
@@ -0,0 +1,73 @@+import Data.DecisionTree++decideProp = (map (decide tree) unlabeled) == labels where+ tree = build atts dataset+++outlook = A { aName = "outlook", possibleValues=["sunny", "overcast", "rainy"] }+temperature = A { aName ="temperature", possibleValues=["hot","mild", "cool"] }+humidity = A { aName ="humidity", possibleValues=["high","normal"] }+windy = A { aName ="windy", possibleValues=["true","false"]}++atts = [outlook,temperature,humidity,windy]++dataset = zip labels unlabeled+labels = ["no","no","yes","yes","yes","no","yes","no","yes","yes","yes","yes","yes","no"]+unlabeled = + [D { dName = "", attributes = [(outlook,"sunny"), + (temperature,"hot"), + (humidity,"high"),+ (windy,"false")]},+ D { dName = "", attributes = [(outlook,"sunny"), + (temperature,"hot"), + (humidity, "high"), + (windy,"true")]},+ D { dName = "", attributes = [(outlook,"overcast"),+ (temperature,"hot"), + (humidity, "high"), + (windy, "false")]},+ D { dName = "", attributes = [(outlook,"rainy"), + (temperature,"mild"), + (humidity, "high"), + (windy,"false")]},+ D { dName = "", attributes = [(outlook,"rainy"), + (temperature, "cool"), + (humidity, "normal"), + (windy,"false")]},+ D { dName = "", attributes = [(outlook, "rainy"), + (temperature,"cool"), + (humidity, "normal"), + (windy, "true")]},+ D { dName = "", attributes = [(outlook, "overcast"), + (temperature, "cool"), + (humidity, "normal"), + (windy,"true")]},+ D { dName = "", attributes = [(outlook, "sunny"), + (temperature, "mild"), + (humidity, "high"), + (windy, "false")]},+ D { dName = "", attributes = [(outlook, "sunny"), + (temperature, "cool"), + (humidity, "normal"), + (windy, "false")]},+ D { dName = "", attributes = [(outlook, "rainy"), + (temperature, "mild"), + (humidity, "normal"), + (windy, "false")]},+ D { dName = "", attributes = [(outlook, "sunny"), + (temperature, "mild"), + (humidity, "normal"), + (windy, "true")]},+ D { dName = "", attributes = [(outlook, "overcast"), + (temperature, "mild"), + (humidity, "high"), + (windy, "true")]},+ D { dName = "", attributes = [(outlook, "overcast"), + (temperature, "hot"), + (humidity, "normal"), + (windy, "false")]},+ D { dName = "", attributes = [(outlook, "rainy"), + (temperature, "mild"), + (humidity, "high"), + (windy,"true")]}]+