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    }