001 /** 002 * Travel2.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.DataBaseConnector; 024 import jcolibri.datatypes.Instance; 025 import jcolibri.exception.ExecutionException; 026 import jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod; 027 import jcolibri.extensions.recommendation.casesDisplay.UserChoice; 028 import jcolibri.extensions.recommendation.conditionals.BuyOrQuit; 029 import jcolibri.extensions.recommendation.conditionals.ContinueOrFinish; 030 import jcolibri.method.gui.formFilling.ObtainQueryWithFormMethod; 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.EnumCyclicDistance; 036 import jcolibri.method.retrieve.NNretrieval.similarity.local.Equal; 037 import jcolibri.method.retrieve.NNretrieval.similarity.local.Interval; 038 import jcolibri.method.retrieve.NNretrieval.similarity.local.Threshold; 039 import jcolibri.method.retrieve.NNretrieval.similarity.local.ontology.OntCosine; 040 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.InrecaLessIsBetter; 041 import jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders.McSherryMoreIsBetter; 042 import jcolibri.method.retrieve.selection.SelectCases; 043 import jcolibri.test.recommenders.travelData.TravelDescription; 044 import jcolibri.test.recommenders.travelData.TravelDescription.AccommodationTypes; 045 import jcolibri.test.recommenders.travelData.TravelDescription.Seasons; 046 import jcolibri.util.FileIO; 047 import es.ucm.fdi.gaia.ontobridge.OntoBridge; 048 import es.ucm.fdi.gaia.ontobridge.OntologyDocument; 049 050 /** 051 * Conversational (type A) trips recommender using form-filling, Nearest Neighbour retrieval and top k selection . 052 * This recommender obtains the user preferences using a form. Then it computes 053 * Nearest Neighbour scoring to obtain the most similar cases. 054 * If the user does not find the desired item, he/she can refine the requirements 055 * using again a form. The form contains initial values and some attributes are 056 * hidden (defined by the designer). 057 * <br>Summary: 058 * <ul> 059 * <li>Type: Conversational A 060 * <li>Case base: travel 061 * <li>One off Preference Elicitation: Form Filling with initial values, hidden attributes and custom labels 062 * <li>Retrieval: NN + topKselection 063 * <li>Display: In table 064 * <li>Iterated Preference Elecitiation: Form Filling with initial values, hidden attributes and custom labels 065 * </ul> 066 * This recommender implements the following template:<br> 067 * <center><img src="../Template2_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.gui.formFilling.ObtainQueryWithFormMethod 073 * @see jcolibri.method.retrieve.NNretrieval.NNScoringMethod 074 * @see jcolibri.method.retrieve.selection.SelectCases 075 * @see jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod 076 * 077 * @author Juan A. Recio-Garcia 078 * @author Developed at University College Cork (Ireland) in collaboration with Derek Bridge. 079 * @version 1.0 080 */ 081 public class Travel2 implements StandardCBRApplication 082 { 083 /** Connector object */ 084 Connector _connector; 085 /** CaseBase object */ 086 CBRCaseBase _caseBase; 087 088 /** KNN config */ 089 NNConfig simConfig; 090 091 /** hidden attributes for obtain query */ 092 Collection<Attribute> hiddenAtts; 093 /** custum labels for obtain query */ 094 Map<Attribute,String> labels; 095 096 097 public void configure() throws ExecutionException 098 { 099 //Emulate data base server 100 jcolibri.test.database.HSQLDBserver.init(); 101 102 // Create a data base connector 103 _connector = new DataBaseConnector(); 104 // Init the ddbb connector with the config file 105 _connector.initFromXMLfile(jcolibri.util.FileIO 106 .findFile("jcolibri/test/recommenders/travelData/databaseconfig.xml")); 107 // Create a Lineal case base for in-memory organization 108 _caseBase = new LinealCaseBase(); 109 110 // Obtain a reference to OntoBridge 111 OntoBridge ob = jcolibri.util.OntoBridgeSingleton.getOntoBridge(); 112 // Configure it to work with the Pellet reasoner 113 ob.initWithPelletReasoner(); 114 // Setup the main ontology 115 OntologyDocument mainOnto = new OntologyDocument("http://gaia.fdi.ucm.es/ontologies/travel-destinations.owl", 116 FileIO.findFile("jcolibri/test/recommenders/travelData/travel-destinations.owl").toExternalForm()); 117 // There are not subontologies 118 ArrayList<OntologyDocument> subOntologies = new ArrayList<OntologyDocument>(); 119 // Load the ontology 120 ob.loadOntology(mainOnto, subOntologies, false); 121 122 // Configure the KNN 123 simConfig = new NNConfig(); 124 // Set the average() global similarity function for the description of the case 125 simConfig.setDescriptionSimFunction(new Average()); 126 // HolidayType --> equal() 127 simConfig.addMapping(new Attribute("HolidayType", TravelDescription.class), new Equal()); 128 // NumberOfPersons --> Threshold(2) 129 simConfig.addMapping(new Attribute("NumberOfPersons", TravelDescription.class), new Threshold(2)); 130 // Region --> ontCosine() 131 simConfig.addMapping(new Attribute("Region", TravelDescription.class), new OntCosine()); 132 // Transportation --> equal() 133 simConfig.addMapping(new Attribute("Transportation", TravelDescription.class), new Equal()); 134 // Duration --> interval(31) 135 simConfig.addMapping(new Attribute("Duration", TravelDescription.class), new Interval(31)); 136 // Season --> EnumCyclicDistance 137 simConfig.addMapping(new Attribute("Season", TravelDescription.class), new EnumCyclicDistance()); 138 // Accomodation --> McSherryMoreIsBetter 139 simConfig.addMapping(new Attribute("Accommodation", TravelDescription.class), new McSherryMoreIsBetter(0,0)); 140 // Price --> InrecaLessIsBetter(4000) 141 simConfig.addMapping(new Attribute("Price", TravelDescription.class), new InrecaLessIsBetter(4000, 0.5)); 142 143 144 145 // Configuration objects for obtain query 146 hiddenAtts = new ArrayList<Attribute>(); 147 hiddenAtts.add(new Attribute("Accommodation", TravelDescription.class)); 148 labels = new HashMap<Attribute,String>(); 149 labels.put(new Attribute("Price", TravelDescription.class), "Max price"); 150 } 151 152 public void cycle(CBRQuery query) throws ExecutionException 153 { 154 // Obtain query 155 ObtainQueryWithFormMethod.obtainQueryWithInitialValues(query,hiddenAtts,labels); 156 157 // Jump to converstaion cycle 158 sequence1(query); 159 } 160 161 162 public void sequence1(CBRQuery query) 163 { 164 // Execute KNN 165 Collection<RetrievalResult> eval = NNScoringMethod.evaluateSimilarity(_caseBase.getCases(), query, simConfig); 166 167 // Select cases 168 Collection<CBRCase> retrievedCases = SelectCases.selectTopK(eval, 5); 169 170 // Display cases 171 UserChoice choice = DisplayCasesTableMethod.displayCasesInTableEditQuery(retrievedCases); 172 // Continue or Finish? 173 if(ContinueOrFinish.continueOrFinish(choice)) 174 sequence2(query); 175 else 176 sequence3(choice, retrievedCases); 177 } 178 179 public void sequence2(CBRQuery query) 180 { 181 // Obtain query again 182 ObtainQueryWithFormMethod.obtainQueryWithInitialValues(query,hiddenAtts,labels); 183 184 185 //Jump to converstaion cycle 186 sequence1(query); 187 } 188 189 public void sequence3(UserChoice choice, Collection<CBRCase> retrievedCases) 190 { 191 // Buy or Quit? 192 if(BuyOrQuit.buyOrQuit(choice)) 193 System.out.println("Finish - User Buys: "+choice.getSelectedCase()); 194 else 195 System.out.println("Finish - User Quits"); 196 } 197 198 public void postCycle() throws ExecutionException 199 { 200 _connector.close(); 201 jcolibri.test.database.HSQLDBserver.shutDown(); 202 } 203 204 public CBRCaseBase preCycle() throws ExecutionException 205 { 206 // Load cases from connector into the case base 207 _caseBase.init(_connector); 208 // Print the cases 209 java.util.Collection<CBRCase> cases = _caseBase.getCases(); 210 for(CBRCase c: cases) 211 System.out.println(c); 212 return _caseBase; 213 } 214 215 public static void main(String[] args) { 216 StandardCBRApplication recommender = new Travel2(); 217 try 218 { 219 recommender.configure(); 220 221 recommender.preCycle(); 222 223 CBRQuery query = new CBRQuery(); 224 225 TravelDescription td = new TravelDescription(); 226 td.setAccommodation(AccommodationTypes.ThreeStars); 227 td.setDuration(7); 228 td.setHolidayType("bathing"); 229 td.setNumberOfPersons(2); 230 td.setRegion(new Instance("Spain")); 231 td.setSeason(Seasons.July); 232 td.setTransportation("plane"); 233 td.setPrice(1000); 234 235 query.setDescription(td); 236 237 recommender.cycle(query); 238 239 recommender.postCycle(); 240 241 System.exit(0); 242 } catch (Exception e) 243 { 244 org.apache.commons.logging.LogFactory.getLog(Travel2.class).error(e); 245 246 } 247 248 249 } 250 251 }