001 /** 002 * Houses5.java 003 * jCOLIBRI2 framework. 004 * @author Juan A. Recio-García. 005 * GAIA - Group for Artificial Intelligence Applications 006 * http://gaia.fdi.ucm.es 007 * 23/10/2007 008 */ 009 package jcolibri.test.recommenders.rec5; 010 011 import java.util.ArrayList; 012 import java.util.Collection; 013 import java.util.HashMap; 014 import java.util.Map; 015 016 import jcolibri.casebase.LinealCaseBase; 017 import jcolibri.cbraplications.StandardCBRApplication; 018 import jcolibri.cbrcore.Attribute; 019 import jcolibri.cbrcore.CBRCase; 020 import jcolibri.cbrcore.CBRCaseBase; 021 import jcolibri.cbrcore.CBRQuery; 022 import jcolibri.cbrcore.Connector; 023 import jcolibri.connector.PlainTextConnector; 024 import jcolibri.exception.ExecutionException; 025 import jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod; 026 import jcolibri.extensions.recommendation.casesDisplay.UserChoice; 027 import jcolibri.extensions.recommendation.conditionals.BuyOrQuit; 028 import jcolibri.extensions.recommendation.conditionals.ContinueOrFinish; 029 import jcolibri.extensions.recommendation.navigationByAsking.ObtainQueryWithAttributeQuestionMethod; 030 import jcolibri.extensions.recommendation.navigationByAsking.SimilarityInfluence; 031 import jcolibri.method.retrieve.RetrievalResult; 032 import jcolibri.method.retrieve.NNretrieval.NNConfig; 033 import jcolibri.method.retrieve.NNretrieval.NNScoringMethod; 034 import jcolibri.method.retrieve.NNretrieval.similarity.global.Average; 035 import jcolibri.method.retrieve.NNretrieval.similarity.local.Equal; 036 import jcolibri.method.retrieve.NNretrieval.similarity.local.Table; 037 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaLessIsBetter; 038 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaMoreIsBetter; 039 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.McSherryMoreIsBetter; 040 import jcolibri.method.retrieve.selection.SelectCases; 041 import jcolibri.test.recommenders.housesData.HouseDescription; 042 043 /** 044 * Conversational (type A) flats recommender using Navigation by Asking and KNN retrieval. 045 * <br> 046 * This recommender combines Navigation by Asking and Nearest Neighbour retrieval. 047 * To select the attribute asked to the user, it applies the Similarity Influence method. 048 * Then, the NN scoring method is executed and the retrieved items are presented to the 049 * user. If the user does not find the desired item, the system asks again for the value 050 * of another attribute. 051 * <br> 052 * Note!: the Similarity influence method runs very slowly. To speed up the execution, only 053 * 200 items are loaded. 054 * <br>Summary: 055 * <ul> 056 * <li>Type: Conversational A 057 * <li>Case base: houses 058 * <li>One off Preference Elicitation: Navigation by Asking using Similarity Influence (note: that method is very slow) 059 * <li>Retrieval: NN + topKselection 060 * <li>Display: In table 061 * <li>Iterated Preference Elecitiation: Navigation by Asking using Similarity Influence (note: that method is very slow) 062 * </ul> 063 * This recommender implements the following template:<br> 064 * <center><img src="../Template5_Cycle.jpg"/></center> 065 * 066 * <br>Read the documentation of the recommenders extension for details about templates 067 * and recommender strategies: {@link jcolibri.extensions.recommendation} 068 * 069 * @see jcolibri.extensions.recommendation.navigationByAsking.ObtainQueryWithAttributeQuestionMethod 070 * @see jcolibri.extensions.recommendation.navigationByAsking.SimilarityInfluence 071 * @see jcolibri.method.retrieve.NNretrieval.NNScoringMethod 072 * @see jcolibri.method.retrieve.selection.SelectCases 073 * @see jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod 074 * 075 * @author Juan A. Recio-Garcia 076 * @author Developed at University College Cork (Ireland) in collaboration with Derek Bridge. 077 * @version 1.0 078 */ 079 public class Houses5 implements StandardCBRApplication 080 { 081 /** Connector object */ 082 Connector _connector; 083 /** CaseBase object */ 084 CBRCaseBase _caseBase; 085 086 /** NN configuration*/ 087 NNConfig simConfig; 088 089 /** Obtain query configuration*/ 090 Collection<Attribute> hiddenAtts; 091 /** Obtain query configuration*/ 092 Map<Attribute,String> labels; 093 094 //MODIFICATION TO SPEED UP THE EXECUTION 095 Collection<CBRCase> workingCases; 096 097 public void configure() throws ExecutionException 098 { 099 // Create a data base connector 100 _connector = new PlainTextConnector(); 101 // Init the ddbb connector with the config file 102 _connector.initFromXMLfile(jcolibri.util.FileIO 103 .findFile("jcolibri/test/recommenders/housesData/plaintextconfig.xml")); 104 // Create a Lineal case base for in-memory organization 105 _caseBase = new LinealCaseBase(); 106 107 //Lets configure the KNN 108 simConfig = new NNConfig(); 109 // Set the average() global similarity function for the description of the case 110 simConfig.setDescriptionSimFunction(new Average()); 111 simConfig.addMapping(new Attribute("area", HouseDescription.class), new Table("jcolibri/test/recommenders/housesData/area.csv")); 112 simConfig.addMapping(new Attribute("beds", HouseDescription.class), new McSherryMoreIsBetter(0,0)); 113 simConfig.addMapping(new Attribute("price", HouseDescription.class), new InrecaLessIsBetter(2000, 0.5)); 114 simConfig.addMapping(new Attribute("furnished", HouseDescription.class), new Equal()); 115 simConfig.addMapping(new Attribute("type", HouseDescription.class), new Equal()); 116 simConfig.addMapping(new Attribute("baths", HouseDescription.class), new InrecaMoreIsBetter(0.5)); 117 118 119 // Configure obtain query method 120 hiddenAtts = new ArrayList<Attribute>(); 121 hiddenAtts.add(new Attribute("beds", HouseDescription.class)); 122 labels = new HashMap<Attribute,String>(); 123 labels.put(new Attribute("price", HouseDescription.class), "Max price"); 124 labels.put(new Attribute("baths", HouseDescription.class), "Min bahtrooms"); 125 126 } 127 128 public void cycle(CBRQuery query) throws ExecutionException 129 { 130 // Select attribute using SimVar 131 Collection<CBRCase> loadedCases = _caseBase.getCases(); 132 133 // MODIFICATION TO SPEED UP THE EXECUTION 134 workingCases = new ArrayList<CBRCase>(); 135 java.util.Iterator<CBRCase> iter = loadedCases.iterator(); 136 for(int i=0; i<200; i++) 137 workingCases.add(iter.next()); 138 // MODIFICATION END 139 140 Attribute att = SimilarityInfluence.getMoreSimVarAttribute(workingCases,query, simConfig, true); 141 142 // Obtain attribute value 143 ObtainQueryWithAttributeQuestionMethod.obtainQueryWithAttributeQuestion(query, att, labels, workingCases); 144 145 // Go to main conversation cycle 146 sequence1(query); 147 148 } 149 150 151 public void sequence1(CBRQuery query) throws ExecutionException 152 { 153 // Execute KNN 154 // MODIFICATION TO SPEED UP THE EXECUTION. Use _caseBase.getCases() insead working cases 155 // to use the whole case base. 156 Collection<RetrievalResult> eval = NNScoringMethod.evaluateSimilarity(workingCases, query, simConfig); 157 158 // Select cases 159 Collection<CBRCase> retrievedCases = SelectCases.selectTopK(eval, 5); 160 161 // Display cases 162 UserChoice choice = DisplayCasesTableMethod.displayCasesInTableEditQuery(retrievedCases); 163 164 if(ContinueOrFinish.continueOrFinish(choice)) 165 sequence2(query); 166 else 167 sequence3(choice, retrievedCases); 168 } 169 170 public void sequence2(CBRQuery query) throws ExecutionException 171 { 172 // Select attribute using SimVar 173 174 // MODIFICATION TO SPEED UP THE EXECUTION. Use _caseBase.getCases() insead working cases 175 // to use the whole case base. 176 //Collection<CBRCase> workingCases = _caseBase.getCases(); 177 178 Attribute att = SimilarityInfluence.getMoreSimVarAttribute(workingCases,query, simConfig, true); 179 180 // Obtain attribute value 181 ObtainQueryWithAttributeQuestionMethod.obtainQueryWithAttributeQuestion(query, att, labels, workingCases); 182 183 // Go to main conversation cycle 184 sequence1(query); 185 } 186 187 public void sequence3(UserChoice choice, Collection<CBRCase> retrievedCases) throws ExecutionException 188 { 189 if(BuyOrQuit.buyOrQuit(choice)) 190 System.out.println("Finish - User Buys: "+choice.getSelectedCase()); 191 192 else 193 System.out.println("Finish - User Quits"); 194 } 195 196 public void postCycle() throws ExecutionException 197 { 198 } 199 200 public CBRCaseBase preCycle() throws ExecutionException 201 { 202 // Load cases from connector into the case base 203 _caseBase.init(_connector); 204 // Print the cases 205 java.util.Collection<CBRCase> cases = _caseBase.getCases(); 206 for(CBRCase c: cases) 207 System.out.println(c); 208 return _caseBase; 209 } 210 211 public static void main(String[] args) { 212 213 //SwingProgressBar shows the progress 214 jcolibri.util.ProgressController.clear(); 215 jcolibri.util.ProgressController.register(new jcolibri.test.main.SwingProgressBar(), SimilarityInfluence.class); 216 217 218 StandardCBRApplication recommender = new Houses5(); 219 try 220 { 221 recommender.configure(); 222 223 recommender.preCycle(); 224 225 CBRQuery query = new CBRQuery(); 226 227 HouseDescription hd = new HouseDescription(); 228 229 query.setDescription(hd); 230 231 recommender.cycle(query); 232 233 recommender.postCycle(); 234 235 //System.exit(0); 236 } catch (Exception e) 237 { 238 org.apache.commons.logging.LogFactory.getLog(Houses5.class).error(e); 239 240 } 241 242 243 } 244 245 }