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