001 package jcolibri.method.maintenance.solvesFunctions; 002 003 import java.util.Collection; 004 import java.util.Iterator; 005 import java.util.LinkedList; 006 007 import jcolibri.cbrcore.CBRCase; 008 import jcolibri.extensions.classification.ClassificationSolution; 009 import jcolibri.method.maintenance.SolvesFunction; 010 import jcolibri.method.retrieve.RetrievalResult; 011 import jcolibri.method.retrieve.NNretrieval.NNScoringMethod; 012 import jcolibri.method.retrieve.selection.SelectCases; 013 import jcolibri.method.reuse.classification.KNNClassificationConfig; 014 import jcolibri.method.reuse.classification.KNNClassificationMethod; 015 import jcolibri.method.revise.classification.BasicClassificationOracle; 016 import jcolibri.method.revise.classification.ClassificationOracle; 017 018 /** 019 * Provides the solves function that Sarah-Jane Delaney uses 020 * in her case-base editing (CBE) algorithms which will 021 * decide which cases solve a query. 022 * 023 * @author Lisa Cummins 024 * @author Derek Bridge 025 * 22/05/07 026 */ 027 public class CBESolvesFunction extends SolvesFunction 028 { 029 /** 030 * Sets the cases that either solve q or contribute to its 031 * misclassification. 032 * A case solves a query if the query is correctly classified 033 * by its nearest neighbours and the solution of the case 034 * agrees with the solution of the query. 035 * A case misclassifies a query if the query is incorrectly 036 * classified by its nearest neighbours and the solution of the 037 * case disagrees with the solution of the query. 038 * 039 * @param q the query 040 * @param cases from which to find the cases which solve 041 * and classify the query. These include the query itself. 042 * @param knnConfig the similarity configuration 043 */ 044 public void setCasesThatSolveAndMisclassifyQ(CBRCase q, Collection<CBRCase> cases, KNNClassificationConfig knnConfig) 045 { 046 solveQ = new LinkedList<CBRCase>(); //It will always contain at least the query itself 047 misclassifyQ = null; 048 049 /* q is regarded to solve itself regardless of whether it is 050 * correctly or incorrectly classified by its nearest neighbours 051 * and so we add it to its solveQ set. 052 */ 053 solveQ.add(q); 054 055 /* Because q is included in the cases, we retrieve k+1 neighbours and then 056 * either remove q, or, if q is not contained in the retrieved cases, we 057 * remove the last case of those retrieved 058 */ 059 knnConfig.setK(knnConfig.getK()+1); 060 Collection<RetrievalResult> knnResults = NNScoringMethod.evaluateSimilarity(cases, q, knnConfig); 061 Collection<CBRCase> knn = SelectCases.selectTopK(knnResults, knnConfig.getK()); 062 knnConfig.setK(knnConfig.getK()-1); 063 RetrievalResult result = null; 064 boolean qFound = false; 065 066 for(Iterator<RetrievalResult> cIter = knnResults.iterator(); cIter.hasNext() && !qFound; ) 067 { result = cIter.next(); 068 if(result.get_case().equals(q)) 069 { knnResults.remove(result); 070 qFound = true; 071 } 072 } 073 if(!qFound) 074 { knn.remove(result); 075 } 076 try 077 { KNNClassificationMethod classifier = ((KNNClassificationConfig)knnConfig).getClassificationMethod(); 078 ClassificationSolution predictedSolution = classifier.getPredictedSolution(knnResults); 079 080 ClassificationOracle oracle = new BasicClassificationOracle(); 081 boolean correct = oracle.isCorrectPrediction(predictedSolution, q); 082 if(correct) 083 { for(RetrievalResult res: knnResults) 084 { CBRCase c = res.get_case(); 085 if(oracle.isCorrectPrediction((ClassificationSolution)c.getSolution(), q)) 086 { solveQ.add(c); 087 } 088 } 089 } 090 else 091 { misclassifyQ = new LinkedList<CBRCase>(); 092 for(RetrievalResult res: knnResults) 093 { CBRCase c = res.get_case(); 094 if(!oracle.isCorrectPrediction((ClassificationSolution)c.getSolution(), q)) 095 { misclassifyQ.add(c); 096 } 097 } 098 099 } 100 } catch(ClassCastException cce) 101 { org.apache.commons.logging.LogFactory.getLog(CBESolvesFunction.class).error(cce); 102 System.exit(0); 103 } 104 105 } 106 }