001    package jcolibri.method.maintenance.algorithms;
002    
003    import java.util.Collection;
004    import java.util.LinkedList;
005    import java.util.List;
006    import java.util.ListIterator;
007    
008    import jcolibri.cbrcore.CBRCase;
009    import jcolibri.extensions.classification.ClassificationSolution;
010    import jcolibri.method.maintenance.AbstractCaseBaseEditMethod;
011    import jcolibri.method.retrieve.RetrievalResult;
012    import jcolibri.method.retrieve.NNretrieval.NNScoringMethod;
013    import jcolibri.method.retrieve.selection.SelectCases;
014    import jcolibri.method.reuse.classification.KNNClassificationConfig;
015    import jcolibri.method.reuse.classification.KNNClassificationMethod;
016    import jcolibri.method.revise.classification.BasicClassificationOracle;
017    import jcolibri.method.revise.classification.ClassificationOracle;
018    
019    /**
020     * Provides the ability to run the RENN case base editing algorithm 
021     * on a case base to eliminate noise.
022     * 
023     * @author Lisa Cummins
024     * @author Derek Bridge
025     * 18/05/07
026     */
027    public class RENNNoiseReduction extends AbstractCaseBaseEditMethod {
028    
029            /**
030             * Simulates the RENN case base editing algorithm, returning the cases
031             * that would be deleted by the algorithm.
032             * @param cases The group of cases on which to perform editing.
033             * @param simConfig The similarity configuration for these cases.
034             * @return the list of cases that would be deleted by the 
035             * RENN algorithm.
036             */
037            public Collection<CBRCase> retrieveCasesToDelete(Collection<CBRCase> cases, KNNClassificationConfig simConfig) 
038            {       /* RENN Algorithm:
039                     *
040                     * T: Training Set
041                     * 
042                     * Repeat
043                     *              changes = false
044                     *              For all x E T do
045                     *                      If x does not agree with the majority of its NN
046                     *                              T = T - {x}
047                     *                              changes = true
048                     *                      End-If
049                     *              End-For
050                     * Until not changes
051                     *
052                     * Return T     
053                     */
054                    jcolibri.util.ProgressController.init(this.getClass(),"RENN Noise Reduction",jcolibri.util.ProgressController.UNKNOWN_STEPS);
055                    List<CBRCase> localCases = new LinkedList<CBRCase>();
056                    
057                    for(CBRCase c: cases)
058                    {       localCases.add(c);
059                    }
060                    
061                    List<CBRCase> allCasesToBeRemoved = new LinkedList<CBRCase>();
062    
063                    boolean changes = true;
064                    while(changes && localCases.size() > 1)
065                    {       changes = false;
066                            ListIterator<CBRCase> iter = localCases.listIterator();   
067                            while (iter.hasNext())
068                            {       CBRCase q = iter.next();
069                                    iter.remove();
070                                    Collection<RetrievalResult> knn = NNScoringMethod.evaluateSimilarity(localCases, q, simConfig);
071                                    knn = SelectCases.selectTopKRR(knn, simConfig.getK());
072                                    try
073                                    {       KNNClassificationMethod classifier = ((KNNClassificationConfig)simConfig).getClassificationMethod();
074                                            ClassificationSolution predictedSolution = classifier.getPredictedSolution(knn);
075                                            ClassificationOracle oracle = new BasicClassificationOracle();
076                                            if(!oracle.isCorrectPrediction(predictedSolution, q))
077                                            {       allCasesToBeRemoved.add(q);
078                                                    changes = true;
079                                            }
080                                            else
081                                            {       iter.add(q);
082                                            }
083                                    } catch(ClassCastException cce)
084                                    {       org.apache.commons.logging.LogFactory.getLog(RENNNoiseReduction.class).error(cce);
085                                            System.exit(0);
086                                    }
087                            }
088                            jcolibri.util.ProgressController.step(this.getClass());
089                    }
090                    jcolibri.util.ProgressController.finish(this.getClass());
091                    return allCasesToBeRemoved;
092            }
093    }