001 /** 002 * Houses2.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.rec2; 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.method.gui.formFilling.ObtainQueryWithFormMethod; 030 import jcolibri.method.retrieve.RetrievalResult; 031 import jcolibri.method.retrieve.NNretrieval.NNConfig; 032 import jcolibri.method.retrieve.NNretrieval.NNScoringMethod; 033 import jcolibri.method.retrieve.NNretrieval.similarity.global.Average; 034 import jcolibri.method.retrieve.NNretrieval.similarity.local.Equal; 035 import jcolibri.method.retrieve.NNretrieval.similarity.local.Table; 036 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaLessIsBetter; 037 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaMoreIsBetter; 038 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.McSherryMoreIsBetter; 039 import jcolibri.method.retrieve.selection.SelectCases; 040 import jcolibri.test.recommenders.housesData.HouseDescription; 041 042 /** 043 * Conversational (type A) flats recommender using form-filling, Nearest Neighbour retrieval and top k selection . 044 * <br> 045 * This recommender obtains the user preferences using a form. Then it computes 046 * Nearest Neighbour scoring to obtain the most similar cases. 047 * If the user does not find the desired item, he/she can refine the requirements 048 * using again a form. The form contains initial values and some attributes are 049 * hidden (defined by the designer). 050 * <br>Summary: 051 * <ul> 052 * <li>Type: Conversational A 053 * <li>Case base: houses 054 * <li>One off Preference Elicitation: Form Filling with initial values, hidden attributes and custom labels 055 * <li>Retrieval: Nearest Neighbour + topKselection 056 * <li>Display: In table 057 * <li>Iterated Preference Elecitiation: Form Filling with initial values, hidden attributes and custom labels 058 * </ul> 059 * This recommender implements the following template:<br> 060 * <center><img src="../Template2_Cycle.jpg"/></center> 061 * 062 * <br>Read the documentation of the recommenders extension for details about templates 063 * and recommender strategies: {@link jcolibri.extensions.recommendation} 064 * 065 * @see jcolibri.method.gui.formFilling.ObtainQueryWithFormMethod 066 * @see jcolibri.method.retrieve.NNretrieval.NNScoringMethod 067 * @see jcolibri.method.retrieve.selection.SelectCases 068 * @see jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod 069 * 070 * @author Juan A. Recio-Garcia 071 * @author Developed at University College Cork (Ireland) in collaboration with Derek Bridge. 072 * @version 1.0 073 */ 074 public class Houses2 implements StandardCBRApplication 075 { 076 /** Connector object */ 077 Connector _connector; 078 /** CaseBase object */ 079 CBRCaseBase _caseBase; 080 081 /** KNN Config */ 082 NNConfig simConfig; 083 084 /** Configuration objects for obtain query */ 085 Collection<Attribute> hiddenAtts; 086 /** Configuration objects for obtain query */ 087 Map<Attribute,String> labels; 088 089 public void configure() throws ExecutionException 090 { 091 // Create a data base connector 092 _connector = new PlainTextConnector(); 093 // Init the ddbb connector with the config file 094 _connector.initFromXMLfile(jcolibri.util.FileIO 095 .findFile("jcolibri/test/recommenders/housesData/plaintextconfig.xml")); 096 // Create a Lineal case base for in-memory organization 097 _caseBase = new LinealCaseBase(); 098 099 //Configure the KNN 100 simConfig = new NNConfig(); 101 // Set the average() global similarity function for the description of the case 102 simConfig.setDescriptionSimFunction(new Average()); 103 simConfig.addMapping(new Attribute("area", HouseDescription.class), new Table("jcolibri/test/recommenders/housesData/area.csv")); 104 simConfig.addMapping(new Attribute("beds", HouseDescription.class), new McSherryMoreIsBetter(0,0)); 105 simConfig.addMapping(new Attribute("price", HouseDescription.class), new InrecaLessIsBetter(2000, 0.5)); 106 simConfig.addMapping(new Attribute("furnished", HouseDescription.class), new Equal()); 107 simConfig.addMapping(new Attribute("type", HouseDescription.class), new Equal()); 108 simConfig.addMapping(new Attribute("baths", HouseDescription.class), new InrecaMoreIsBetter(0.5)); 109 110 111 // Configuration objects for obtain query 112 hiddenAtts = new ArrayList<Attribute>(); 113 hiddenAtts.add(new Attribute("beds", HouseDescription.class)); 114 labels = new HashMap<Attribute,String>(); 115 labels.put(new Attribute("price", HouseDescription.class), "Max price"); 116 labels.put(new Attribute("baths", HouseDescription.class), "Min bahtrooms"); 117 } 118 119 public void cycle(CBRQuery query) throws ExecutionException 120 { 121 //Obtain the query 122 ObtainQueryWithFormMethod.obtainQueryWithInitialValues(query,hiddenAtts,labels); 123 124 //Jump to converstaion cycle 125 sequence1(query); 126 } 127 128 129 public void sequence1(CBRQuery query) 130 { 131 // Execute KNN 132 Collection<RetrievalResult> eval = NNScoringMethod.evaluateSimilarity(_caseBase.getCases(), query, simConfig); 133 134 // Select cases 135 Collection<CBRCase> retrievedCases = SelectCases.selectTopK(eval, 5); 136 137 // Display cases 138 UserChoice choice = DisplayCasesTableMethod.displayCasesInTableEditQuery(retrievedCases); 139 140 // Continue or Finish 141 if(ContinueOrFinish.continueOrFinish(choice)) 142 sequence2(query); 143 else 144 sequence3(choice, retrievedCases); 145 } 146 147 public void sequence2(CBRQuery query) 148 { 149 // Obtain query again 150 ObtainQueryWithFormMethod.obtainQueryWithInitialValues(query,hiddenAtts,labels); 151 152 // Jump to conversation cycle 153 sequence1(query); 154 } 155 156 157 public void sequence3(UserChoice choice, Collection<CBRCase> retrievedCases) 158 { 159 // Finishing: buy or quit 160 if(BuyOrQuit.buyOrQuit(choice)) 161 System.out.println("Finish - User Buys: "+choice.getSelectedCase()); 162 163 else 164 System.out.println("Finish - User Quits"); 165 } 166 167 public void postCycle() throws ExecutionException 168 { 169 } 170 171 public CBRCaseBase preCycle() throws ExecutionException 172 { 173 // Load cases from connector into the case base 174 _caseBase.init(_connector); 175 // Print the cases 176 java.util.Collection<CBRCase> cases = _caseBase.getCases(); 177 for(CBRCase c: cases) 178 System.out.println(c); 179 return _caseBase; 180 } 181 182 public static void main(String[] args) { 183 StandardCBRApplication recommender = new Houses2(); 184 try 185 { 186 recommender.configure(); 187 188 recommender.preCycle(); 189 190 CBRQuery query = new CBRQuery(); 191 192 HouseDescription hd = new HouseDescription(); 193 hd.setArea(HouseDescription.Area.Hampstead); 194 hd.setBaths(1); 195 hd.setBeds(HouseDescription.Beds.two); 196 hd.setFurnished(true); 197 hd.setPrice(500); 198 hd.setType(HouseDescription.Type.Flat); 199 200 query.setDescription(hd); 201 202 recommender.cycle(query); 203 204 recommender.postCycle(); 205 206 //System.exit(0); 207 } catch (Exception e) 208 { 209 org.apache.commons.logging.LogFactory.getLog(Houses2.class).error(e); 210 211 } 212 213 214 } 215 216 }