001 /** 002 * Houses11.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.rec11; 010 011 import java.util.Collection; 012 import java.util.HashMap; 013 import jcolibri.casebase.LinealCaseBase; 014 import jcolibri.cbraplications.StandardCBRApplication; 015 import jcolibri.cbrcore.Attribute; 016 import jcolibri.cbrcore.CBRCase; 017 import jcolibri.cbrcore.CBRCaseBase; 018 import jcolibri.cbrcore.CBRQuery; 019 import jcolibri.cbrcore.Connector; 020 import jcolibri.connector.PlainTextConnector; 021 import jcolibri.exception.ExecutionException; 022 import jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod; 023 import jcolibri.extensions.recommendation.casesDisplay.UserChoice; 024 import jcolibri.extensions.recommendation.conditionals.BuyOrQuit; 025 import jcolibri.extensions.recommendation.conditionals.ContinueOrFinish; 026 import jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.LessLikeThis; 027 import jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.MoreAndLessLikeThis; 028 import jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.MoreLikeThis; 029 import jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.PartialMoreLikeThis; 030 import jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.WeightedMoreLikeThis; 031 import jcolibri.method.retrieve.RetrievalResult; 032 import jcolibri.method.retrieve.DiverseByMedianRetrieval.ExpertClerkMedianScoring; 033 import jcolibri.method.retrieve.FilterBasedRetrieval.FilterBasedRetrievalMethod; 034 import jcolibri.method.retrieve.FilterBasedRetrieval.FilterConfig; 035 import jcolibri.method.retrieve.NNretrieval.NNConfig; 036 import jcolibri.method.retrieve.NNretrieval.NNScoringMethod; 037 import jcolibri.method.retrieve.NNretrieval.similarity.global.Average; 038 import jcolibri.method.retrieve.NNretrieval.similarity.local.Equal; 039 import jcolibri.method.retrieve.NNretrieval.similarity.local.Table; 040 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaLessIsBetter; 041 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaMoreIsBetter; 042 import jcolibri.method.retrieve.selection.SelectCases; 043 import jcolibri.test.recommenders.housesData.HouseDescription; 044 045 /** 046 * Conversational (type A) flats recommender using pre-selected cases at one-off preference elicitation, 047 * Navigation By Proposing and Filtering+NearestNeighbour+selectTopK retrieval. 048 * <br> 049 * This recommender follows the Navigation by Proposing strategy and shows the behaviour of several methods 050 * that solve the <i>Iterated Preference Elecitiation</i> task that defines how to modify the user preferences. 051 * There are several methods to obtain a new query from the user selections and critiques: 052 * <ul> 053 * <li>More Like This ({@link jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.MoreLikeThis}) 054 * <li>partial More Like This ({@link jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.PartialMoreLikeThis}) 055 * <li>weighted More Like ({@link jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.WeightedMoreLikeThis}) 056 * <li>Less Like This ({@link jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.LessLikeThis}) 057 * <li>More Like This + Less Like This ({@link jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.MoreAndLessLikeThis}) 058 * <ul> 059 * Modifying the code, the Iterated Preference Elecitiation strategy can be defined before running the example. 060 * <br>Summary: 061 * <ul> 062 * <li>Type: Conversational A 063 * <li>Case base: houses 064 * <li>One off Preference Elicitation: k diverse cases chosen by ExpertClerkMedianScoring and shown in a table + critiques 065 * <li>Retrieval: Filtering + NN + topKselection 066 * <li>Display: In table with find something similar option 067 * <li>Iterated Preference Elecitiation: Navigation by Proposing: by default MLT+LLT. Modifying the code, the replace query strategy can be defined before running the example. 068 * </ul> 069 * This recommender implements the following template:<br> 070 * <center><img src="../Template10_Cycle.jpg"/></center> 071 * 072 * <br>Read the documentation of the recommenders extension for details about templates 073 * and recommender strategies: {@link jcolibri.extensions.recommendation} 074 * 075 * @see jcolibri.method.retrieve.DiverseByMedianRetrieval.ExpertClerkMedianScoring 076 * @see jcolibri.method.retrieve.FilterBasedRetrieval.FilterBasedRetrievalMethod 077 * @see jcolibri.method.retrieve.NNretrieval.NNScoringMethod 078 * @see jcolibri.method.retrieve.selection.SelectCases 079 * @see jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod 080 * 081 * 082 * @author Juan A. Recio-Garcia 083 * @author Developed at University College Cork (Ireland) in collaboration with Derek Bridge. 084 * @version 1.0 085 */ 086 public class Houses11 implements StandardCBRApplication 087 { 088 enum QueryElicitationStrategy {MLT, pMLT, wMLT, LLT, MLT_LLT}; 089 090 private QueryElicitationStrategy strategy; 091 092 /** Connector object */ 093 Connector _connector; 094 /** CaseBase object */ 095 CBRCaseBase _caseBase; 096 097 /** KNN configuration*/ 098 NNConfig simConfig; 099 /** Filter configuration */ 100 FilterConfig filterConfig; 101 102 103 104 public void configure() throws ExecutionException 105 { 106 // Create a data base connector 107 _connector = new PlainTextConnector(); 108 // Init the ddbb connector with the config file 109 _connector.initFromXMLfile(jcolibri.util.FileIO 110 .findFile("jcolibri/test/recommenders/housesData/plaintextconfig.xml")); 111 // Create a Lineal case base for in-memory organization 112 _caseBase = new LinealCaseBase(); 113 114 //Lets configure the KNN 115 simConfig = new NNConfig(); 116 // Set the average() global similarity function for the description of the case 117 simConfig.setDescriptionSimFunction(new Average()); 118 simConfig.addMapping(new Attribute("area", HouseDescription.class), new Table("jcolibri/test/recommenders/housesData/area.csv")); 119 simConfig.addMapping(new Attribute("beds", HouseDescription.class), new InrecaMoreIsBetter(0.5)); 120 simConfig.addMapping(new Attribute("price", HouseDescription.class), new InrecaLessIsBetter(2000, 0.5)); 121 simConfig.addMapping(new Attribute("furnished", HouseDescription.class), new Equal()); 122 simConfig.addMapping(new Attribute("type", HouseDescription.class), new Equal()); 123 simConfig.addMapping(new Attribute("baths", HouseDescription.class), new InrecaMoreIsBetter(0.5)); 124 125 // Filter configuration 126 filterConfig = new FilterConfig(); 127 128 /*// UNCOMMENT THIS CODE TO DEFINE THE ITERATED PREFERENCE ELECITATION BEFORE RUNNING THE EXAMPLE 129 Object[] possibleValues = QueryElicitationStrategy.values(); 130 strategy = (QueryElicitationStrategy)JOptionPane.showInputDialog(null, 131 "Choose one strategy for the example", "Choose strategy", 132 JOptionPane.INFORMATION_MESSAGE, null, 133 possibleValues, possibleValues[0]); 134 */ 135 strategy = QueryElicitationStrategy.MLT_LLT; 136 } 137 138 public void cycle(CBRQuery query) throws ExecutionException 139 { 140 HashMap<Attribute,Double> thresholds = new HashMap<Attribute,Double>(); 141 thresholds.put(new Attribute("beds", HouseDescription.class), 2.0); 142 thresholds.put(new Attribute("price", HouseDescription.class), 300.0); 143 thresholds.put(new Attribute("baths", HouseDescription.class), 2.0); 144 thresholds.put(new Attribute("area", HouseDescription.class), 0.99); 145 thresholds.put(new Attribute("type", HouseDescription.class), 0.99); 146 147 // Retrieve Cases 148 Collection<RetrievalResult> retrievedCases = ExpertClerkMedianScoring.getDiverseByMedian(_caseBase.getCases(), simConfig, thresholds); 149 150 // Select Cases 151 Collection<CBRCase> selectedCases = SelectCases.selectTopK(retrievedCases, 5); 152 153 UserChoice choice = DisplayCasesTableMethod.displayCasesInTableSelectCase(selectedCases); 154 155 // Jump to main conversation 156 sequence1(choice.getSelectedCaseAsQuery()); 157 158 } 159 160 161 public void sequence1(CBRQuery query) throws ExecutionException 162 { 163 // Execute Filter 164 Collection<CBRCase> filtered = FilterBasedRetrievalMethod.filterCases(_caseBase.getCases(), query, filterConfig); 165 166 // Execute NN 167 Collection<RetrievalResult> retrievedCases = NNScoringMethod.evaluateSimilarity(filtered, query, simConfig); 168 169 // Select cases 170 Collection<CBRCase> selectedCases = SelectCases.selectTopK(retrievedCases, 10); 171 172 System.out.println("Retrieved cases"); 173 for(CBRCase c: selectedCases) 174 System.out.println(c); 175 176 // Obtain case 177 UserChoice choice = DisplayCasesTableMethod.displayCasesInTableSelectCase(selectedCases); 178 179 if(ContinueOrFinish.continueOrFinish(choice)) 180 sequence2(query,choice,selectedCases); 181 else 182 sequence3(choice, selectedCases); 183 } 184 185 public void sequence2(CBRQuery query, UserChoice uc, Collection<CBRCase> proposedCases) throws ExecutionException 186 { 187 if(strategy == QueryElicitationStrategy.MLT) 188 MoreLikeThis.moreLikeThis(query, uc.getSelectedCase()); 189 else if(strategy == QueryElicitationStrategy.pMLT) 190 PartialMoreLikeThis.partialMoreLikeThis(query, uc.getSelectedCase(), proposedCases); 191 else if(strategy == QueryElicitationStrategy.wMLT) 192 WeightedMoreLikeThis.weightedMoreLikeThis(query, uc.getSelectedCase(), proposedCases, simConfig); 193 else if(strategy == QueryElicitationStrategy.LLT) 194 LessLikeThis.lessLikeThis(query, uc.getSelectedCase(), proposedCases, filterConfig); 195 else if(strategy == QueryElicitationStrategy.MLT_LLT) 196 MoreAndLessLikeThis.moreAndLessLikeThis(query, uc.getSelectedCase(), proposedCases, filterConfig); 197 198 sequence1(query); 199 } 200 201 public void sequence3(UserChoice choice, Collection<CBRCase> retrievedCases) throws ExecutionException 202 { 203 if(BuyOrQuit.buyOrQuit(choice)) 204 System.out.println("Finish - User Buys: "+choice.getSelectedCase()); 205 206 else 207 System.out.println("Finish - User Quits"); 208 } 209 210 public void postCycle() throws ExecutionException 211 { 212 } 213 214 public CBRCaseBase preCycle() throws ExecutionException 215 { 216 // Load cases from connector into the case base 217 _caseBase.init(_connector); 218 // Print the cases 219 java.util.Collection<CBRCase> cases = _caseBase.getCases(); 220 for(CBRCase c: cases) 221 System.out.println(c); 222 return _caseBase; 223 } 224 225 public static void main(String[] args) { 226 StandardCBRApplication recommender = new Houses11(); 227 try 228 { 229 recommender.configure(); 230 231 recommender.preCycle(); 232 233 CBRQuery query = new CBRQuery(); 234 235 HouseDescription hd = new HouseDescription(); 236 237 query.setDescription(hd); 238 239 recommender.cycle(query); 240 241 recommender.postCycle(); 242 243 //System.exit(0); 244 } catch (Exception e) 245 { 246 org.apache.commons.logging.LogFactory.getLog(Houses11.class).error(e); 247 248 } 249 250 251 } 252 253 }