001 /** 002 * Houses10.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.rec10; 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.UserChoice; 026 import jcolibri.extensions.recommendation.conditionals.BuyOrQuit; 027 import jcolibri.extensions.recommendation.conditionals.ContinueOrFinish; 028 import jcolibri.extensions.recommendation.navigationByProposing.CriticalUserChoice; 029 import jcolibri.extensions.recommendation.navigationByProposing.CritiqueOption; 030 import jcolibri.extensions.recommendation.navigationByProposing.DisplayCasesTableWithCritiquesMethod; 031 import jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.MoreLikeThis; 032 import jcolibri.method.retrieve.RetrievalResult; 033 import jcolibri.method.retrieve.DiverseByMedianRetrieval.ExpertClerkMedianScoring; 034 import jcolibri.method.retrieve.FilterBasedRetrieval.FilterBasedRetrievalMethod; 035 import jcolibri.method.retrieve.FilterBasedRetrieval.FilterConfig; 036 import jcolibri.method.retrieve.FilterBasedRetrieval.predicates.NotEqual; 037 import jcolibri.method.retrieve.FilterBasedRetrieval.predicates.QueryLess; 038 import jcolibri.method.retrieve.FilterBasedRetrieval.predicates.QueryMore; 039 import jcolibri.method.retrieve.NNretrieval.NNConfig; 040 import jcolibri.method.retrieve.NNretrieval.NNScoringMethod; 041 import jcolibri.method.retrieve.NNretrieval.similarity.global.Average; 042 import jcolibri.method.retrieve.NNretrieval.similarity.local.Equal; 043 import jcolibri.method.retrieve.NNretrieval.similarity.local.Table; 044 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaLessIsBetter; 045 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaMoreIsBetter; 046 import jcolibri.method.retrieve.selection.SelectCases; 047 import jcolibri.test.recommenders.housesData.HouseDescription; 048 049 /** 050 * Conversational (type A) flats recommender using pre-selected cases at one-off preference elicitation, 051 * Navigation By Proposing strategy and Filtering+NearestNeighbour+selectTopK retrieval. 052 * <br> 053 * This conversational recommender implements the Navigation by Proposing strategy. Instead of obtaining 054 * the initial query asking to the user, it uses the Expert Clerk Median scoring algorithm to select 055 * k diverse cases that are directly presented to the user in the first iteration. Like other NbP 056 * recommenders it uses critiques to filter the working set of items and computes the Nearest Neighbour 057 * scoring to obtain the displayed items. 058 * <br>Summary: 059 * <ul> 060 * <li>Type: Conversational A 061 * <li>Case base: houses 062 * <li>One off Preference Elicitation: k diverse cases chosen by ExpertClerkMedianScoring and shown in a table + critiques 063 * <li>Retrieval: Filtering + NN + topKselection 064 * <li>Display: In table with critiques 065 * <li>Iterated Preference Elecitiation: Navigation by Proposing: More Like This. 066 * </ul> 067 * This recommender implements the following template:<br> 068 * <center><img src="../Template10_Cycle.jpg"/></center> 069 * 070 * <br>Read the documentation of the recommenders extension for details about templates 071 * and recommender strategies: {@link jcolibri.extensions.recommendation} 072 * 073 * @see jcolibri.method.retrieve.DiverseByMedianRetrieval.ExpertClerkMedianScoring 074 * @see jcolibri.method.retrieve.FilterBasedRetrieval.FilterBasedRetrievalMethod 075 * @see jcolibri.method.retrieve.NNretrieval.NNScoringMethod 076 * @see jcolibri.method.retrieve.selection.SelectCases 077 * @see jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod 078 * @see jcolibri.extensions.recommendation.navigationByProposing.queryElicitation.MoreLikeThis 079 * 080 * 081 * @see jcolibri.test.recommenders.rec6.Houses6 082 * @see jcolibri.test.recommenders.rec9.Houses9 083 * 084 * @author Juan A. Recio-Garcia 085 * @author Developed at University College Cork (Ireland) in collaboration with Derek Bridge. 086 * @version 1.0 087 */ 088 public class Houses10 implements StandardCBRApplication 089 { 090 /** Connector object */ 091 Connector _connector; 092 /** CaseBase object */ 093 CBRCaseBase _caseBase; 094 095 /** KNN configuration*/ 096 NNConfig simConfig; 097 098 /** Obtain query configuration*/ 099 Collection<Attribute> hiddenAtts; 100 /** Obtain query configuration*/ 101 Map<Attribute,String> labels; 102 103 /** Critiques configuration object */ 104 Collection<CritiqueOption> critiques; 105 106 public void configure() throws ExecutionException 107 { 108 // Create a data base connector 109 _connector = new PlainTextConnector(); 110 // Init the ddbb connector with the config file 111 _connector.initFromXMLfile(jcolibri.util.FileIO 112 .findFile("jcolibri/test/recommenders/housesData/plaintextconfig.xml")); 113 // Create a Lineal case base for in-memory organization 114 _caseBase = new LinealCaseBase(); 115 116 //Lets configure the KNN 117 simConfig = new NNConfig(); 118 // Set the average() global similarity function for the description of the case 119 simConfig.setDescriptionSimFunction(new Average()); 120 simConfig.addMapping(new Attribute("area", HouseDescription.class), new Table("jcolibri/test/recommenders/housesData/area.csv")); 121 simConfig.addMapping(new Attribute("beds", HouseDescription.class), new InrecaMoreIsBetter(0.5)); 122 simConfig.addMapping(new Attribute("price", HouseDescription.class), new InrecaLessIsBetter(2000, 0.5)); 123 simConfig.addMapping(new Attribute("furnished", HouseDescription.class), new Equal()); 124 simConfig.addMapping(new Attribute("type", HouseDescription.class), new Equal()); 125 simConfig.addMapping(new Attribute("baths", HouseDescription.class), new InrecaMoreIsBetter(0.5)); 126 127 128 // Obtain query configuration 129 hiddenAtts = new ArrayList<Attribute>(); 130 labels = new HashMap<Attribute,String>(); 131 labels.put(new Attribute("beds", HouseDescription.class), "Min bedrooms"); 132 labels.put(new Attribute("price", HouseDescription.class), "Max price"); 133 labels.put(new Attribute("baths", HouseDescription.class), "Min bahtrooms"); 134 135 // Critiques configuration 136 critiques = new ArrayList<CritiqueOption>(); 137 critiques.add(new CritiqueOption("More Beds",new Attribute("beds", HouseDescription.class),new QueryLess())); 138 critiques.add(new CritiqueOption("Cheaper",new Attribute("price", HouseDescription.class),new QueryMore())); 139 critiques.add(new CritiqueOption("More Bathrooms",new Attribute("baths", HouseDescription.class),new QueryLess())); 140 critiques.add(new CritiqueOption("Change Area",new Attribute("area", HouseDescription.class),new jcolibri.method.retrieve.FilterBasedRetrieval.predicates.Equal())); 141 critiques.add(new CritiqueOption("Another Area",new Attribute("area", HouseDescription.class),new NotEqual())); 142 } 143 144 public void cycle(CBRQuery query) throws ExecutionException 145 { 146 HashMap<Attribute,Double> thresholds = new HashMap<Attribute,Double>(); 147 thresholds.put(new Attribute("beds", HouseDescription.class), 2.0); 148 thresholds.put(new Attribute("price", HouseDescription.class), 300.0); 149 thresholds.put(new Attribute("baths", HouseDescription.class), 2.0); 150 thresholds.put(new Attribute("area", HouseDescription.class), 0.99); 151 thresholds.put(new Attribute("type", HouseDescription.class), 0.99); 152 153 // Retrieve Cases 154 Collection<RetrievalResult> retrievedCases = ExpertClerkMedianScoring.getDiverseByMedian(_caseBase.getCases(), simConfig, thresholds); 155 156 // Select Cases 157 Collection<CBRCase> selectedCases = SelectCases.selectTopK(retrievedCases, 5); 158 159 // Display Cases 160 CriticalUserChoice choice = DisplayCasesTableWithCritiquesMethod.displayCasesInTableWithCritiques(selectedCases, critiques, _caseBase.getCases()); 161 162 // Jump to main conversation 163 sequence1(choice.getSelectedCaseAsQuery(), choice.getFilterConfig()); 164 165 } 166 167 168 public void sequence1(CBRQuery query, FilterConfig filterConfig) throws ExecutionException 169 { 170 // Execute Filter 171 Collection<CBRCase> filtered = FilterBasedRetrievalMethod.filterCases(_caseBase.getCases(), query, filterConfig); 172 173 // Execute NN 174 Collection<RetrievalResult> retrievedCases = NNScoringMethod.evaluateSimilarity(filtered, query, simConfig); 175 176 // Select cases 177 Collection<CBRCase> selectedCases = SelectCases.selectTopK(retrievedCases, 5); 178 179 // Obtain critizied query 180 CriticalUserChoice choice = DisplayCasesTableWithCritiquesMethod.displayCasesInTableWithCritiques(selectedCases, critiques, _caseBase.getCases()); 181 182 if(ContinueOrFinish.continueOrFinish(choice)) 183 sequence2(query,choice); 184 else 185 sequence3(choice, selectedCases); 186 } 187 188 public void sequence2(CBRQuery query, CriticalUserChoice cuc) throws ExecutionException 189 { 190 // Replace current query with the critizied one 191 MoreLikeThis.moreLikeThis(query, cuc.getSelectedCase()); 192 sequence1(query,cuc.getFilterConfig()); 193 } 194 195 public void sequence3(UserChoice choice, Collection<CBRCase> retrievedCases) throws ExecutionException 196 { 197 if(BuyOrQuit.buyOrQuit(choice)) 198 System.out.println("Finish - User Buys: "+choice.getSelectedCase()); 199 200 else 201 System.out.println("Finish - User Quits"); 202 } 203 204 public void postCycle() throws ExecutionException 205 { 206 } 207 208 public CBRCaseBase preCycle() throws ExecutionException 209 { 210 // Load cases from connector into the case base 211 _caseBase.init(_connector); 212 // Print the cases 213 java.util.Collection<CBRCase> cases = _caseBase.getCases(); 214 for(CBRCase c: cases) 215 System.out.println(c); 216 return _caseBase; 217 } 218 219 public static void main(String[] args) { 220 StandardCBRApplication recommender = new Houses10(); 221 try 222 { 223 recommender.configure(); 224 225 recommender.preCycle(); 226 227 CBRQuery query = new CBRQuery(); 228 229 HouseDescription hd = new HouseDescription(); 230 231 query.setDescription(hd); 232 233 recommender.cycle(query); 234 235 recommender.postCycle(); 236 237 } catch (Exception e) 238 { 239 org.apache.commons.logging.LogFactory.getLog(Houses10.class).error(e); 240 241 } 242 243 244 } 245 246 }