001    /*
002     * Created on Aug 2, 2005
003     *
004     */
005    package aima.learning.learners;
006    
007    import java.util.List;
008    
009    import aima.learning.framework.DataSet;
010    import aima.learning.framework.Example;
011    import aima.learning.framework.Learner;
012    import aima.learning.inductive.DLTest;
013    import aima.learning.inductive.DLTestFactory;
014    import aima.learning.inductive.DecisionList;
015    
016    /**
017     * @author Ravi Mohan
018     * 
019     */
020    
021    public class DecisionListLearner implements Learner {
022            public static final String FAILURE = "Failure";
023    
024            private DecisionList decisionList;
025    
026            private String positive, negative;
027    
028            private DLTestFactory testFactory;
029    
030            public DecisionListLearner(String positive, String negative,
031                            DLTestFactory testFactory) {
032                    this.positive = positive;
033                    this.negative = negative;
034                    this.testFactory = testFactory;
035            }
036    
037            public void train(DataSet ds) {
038                    this.decisionList = decisionListLearning(ds);
039            }
040    
041            public String predict(Example e) {
042                    if (decisionList == null) {
043                            throw new RuntimeException(
044                                            "learner has not been trained with dataset yet!");
045                    }
046                    return decisionList.predict(e);
047            }
048    
049            public int[] test(DataSet ds) {
050                    int[] results = new int[] { 0, 0 };
051    
052                    for (Example e : ds.examples) {
053                            if (e.targetValue().equals(decisionList.predict(e))) {
054                                    results[0] = results[0] + 1;
055                            } else {
056                                    results[1] = results[1] + 1;
057                            }
058                    }
059                    return results;
060            }
061    
062            private DecisionList decisionListLearning(DataSet ds) {
063                    if (ds.size() == 0) {
064                            return new DecisionList(positive, negative);
065                    }
066                    List<DLTest> possibleTests = testFactory
067                                    .createDLTestsWithAttributeCount(ds, 1);
068                    DLTest test = getValidTest(possibleTests, ds);
069                    if (test == null) {
070                            return new DecisionList(null, FAILURE);
071                    }
072                    // at this point there is a test that classifies some subset of examples
073                    // with the same target value
074                    DataSet matched = test.matchedExamples(ds);
075                    DecisionList list = new DecisionList(positive, negative);
076                    list.add(test, matched.getExample(0).targetValue());
077                    return list.mergeWith(decisionListLearning(test.unmatchedExamples(ds)));
078            }
079    
080            private DLTest getValidTest(List<DLTest> possibleTests, DataSet ds) {
081                    for (DLTest test : possibleTests) {
082                            DataSet matched = test.matchedExamples(ds);
083                            if (!(matched.size() == 0)) {
084                                    if (allExamplesHaveSameTargetValue(matched)) {
085                                            return test;
086                                    }
087                            }
088    
089                    }
090                    return null;
091            }
092    
093            private boolean allExamplesHaveSameTargetValue(DataSet matched) {
094                    // assumes at least i example in dataset
095                    String targetValue = matched.getExample(0).targetValue();
096                    for (Example e : matched.examples) {
097                            if (!(e.targetValue().equals(targetValue))) {
098                                    return false;
099                            }
100                    }
101                    return true;
102            }
103    
104            /**
105             * @return Returns the decisionList.
106             */
107            public DecisionList getDecisionList() {
108                    return decisionList;
109            }
110    
111    }