001/**
002 * Test3.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 * 10/01/2007
008 */
009package es.ucm.fdi.gaia.jcolibri.test.test3;
010
011
012import java.util.Collection;
013import java.util.HashMap;
014
015import es.ucm.fdi.gaia.jcolibri.casebase.LinealCaseBase;
016import es.ucm.fdi.gaia.jcolibri.cbraplications.StandardCBRApplication;
017import es.ucm.fdi.gaia.jcolibri.cbrcore.Attribute;
018import es.ucm.fdi.gaia.jcolibri.cbrcore.CBRCase;
019import es.ucm.fdi.gaia.jcolibri.cbrcore.CBRCaseBase;
020import es.ucm.fdi.gaia.jcolibri.cbrcore.CBRQuery;
021import es.ucm.fdi.gaia.jcolibri.cbrcore.Connector;
022import es.ucm.fdi.gaia.jcolibri.connector.DataBaseConnector;
023import es.ucm.fdi.gaia.jcolibri.exception.ExecutionException;
024import es.ucm.fdi.gaia.jcolibri.method.retrieve.RetrievalResult;
025import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.NNConfig;
026import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.NNScoringMethod;
027import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.similarity.global.Average;
028import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.similarity.local.Equal;
029import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.similarity.local.Interval;
030import es.ucm.fdi.gaia.jcolibri.method.retrieve.selection.SelectCases;
031import es.ucm.fdi.gaia.jcolibri.method.reuse.CombineQueryAndCasesMethod;
032
033/**
034 * This example shows how to use a compound attribute in the description of a case and how to complete the CBR cycle.
035 * <br>
036 * Now, the description has not a string defining the region. Instead that, it has other bean named "Region" that stores different attributes about the region (nearest city, airport, currency...).
037 * This way, the structure of the case is:
038 * <pre>
039 * Case
040 *  |
041 *  +- Description
042 *          |
043 *          +- caseId
044 *          +- HollidayType
045 *          +- Price
046 *          +- NumberOfPersons
047 *          +- Region
048 *          |     |
049 *          |     +- regionId
050 *          |     +- regionName
051 *          |     +- NearestCity
052 *          |     +- Airport
053 *          |     +- Currency
054 *          +- Transportation
055 *          +- Duration
056 *          +- Season
057 *          +- Accomodation
058 *          +- Hotel
059 * </pre>
060 * <br>
061 * This structure is mapped to the travelext data base that can be created using the travelext.sql file.
062 * It is composed by two tables: travel and region. Travel has a number in the regionid column identifying the row in the region table that contains the information:
063 * <pre>
064 * travel:
065 * +-----------+-------------+-------+-----------------+----------+----------------+----------+-----------+---------------+-----------------------------+
066 * | caseId    | HolidayType | Price | NumberOfPersons | regionId | Transportation | Duration | Season    | Accommodation | Hotel                       |
067 * +-----------+-------------+-------+-----------------+----------+----------------+----------+-----------+---------------+-----------------------------+
068 * | Journey11 | City        |  1978 |               2 |        1 | Plane          |        7 | April     | ThreeStars    | Hotel Victoria, Cairo       |
069 * | Journey21 | Recreation  |  1568 |               2 |        2 | Car            |       14 | May       | TwoStars      | Hotel Ostend, Belgium       |
070 *  ...
071 * region:
072 * +----------+------------+-------------+---------------------------+----------------+
073 * | regionId | RegionName | NearestCity | Airport                   | Currency       |
074 * +----------+------------+-------------+---------------------------+----------------+
075 * |        1 | Cairo      | Cairo       | Cairo Airport             | Egyptian Pound |
076 * |        2 | Belgium    | Brussels    | Brussels National Airport | Euro           |
077 *  ...
078 * </pre>
079 * To map the case structure with the data base we have to modify these lines in hibernate.cfg.xml:
080 * <pre>
081 * &lt;hibernate-mapping default-lazy="false"&gt;
082 *   &lt;class name="es.ucm.fdi.gaia.jcolibri.test.test3.TravelDescription" table="travel"&gt;
083 *      ...
084 *      &lt;many-to-one name="Region" column="regionId" not-null="true" cascade="save-update"/&gt; 
085 *      ...
086 *   &lt;/class&gt;
087 *   &lt;class name="es.ucm.fdi.gaia.jcolibri.test.test3.Region" table="region"&gt;
088 *      &lt;id name="id" column="regionId"&gt;
089 *      &lt;/id&gt;
090 *      &lt;property name="region" column="RegionName"/&gt;
091 *      &lt;property name="city" column="NearestCity"/&gt;
092 *      &lt;property name="airport" column="Airport"/&gt;
093 *      &lt;property name="currency" column="Currency"/&gt;
094 *   &lt;/class&gt;
095 * &lt;/hibernate-mapping&gt;
096 * </pre>
097 * The many-to-one tag indicates the association between the regionId column in the travel table with the values of the region table.
098 * <p>
099 * This example also shows how to complete the CBR cycle including reuse, revise and retain methods:
100 * <ul>
101 * <li>Reuse. To reuse a case we have to combine its solution with the description of the query. 
102 * It is done by the method: CombineQueryAndCasesMethod.combine()
103 * <li>Revise. A simple revision consists on defining new values for the ids of the compound attributes to save the new case into the persistence layer. 
104 * It is done by: DefineNewIdsMethod.defineNewIdsMethod()
105 * <li>Retain. Consists on saving a new case into the persistence layer. This is performed by: StoreCasesMethod.storeCase()
106 * </ul>
107 * 
108 * @author Juan A. Recio-Garcia
109 * @version 1.0
110 * @see es.ucm.fdi.gaia.jcolibri.test.test3.TravelDescription
111 * @see es.ucm.fdi.gaia.jcolibri.test.test3.Region
112 * @see jcolibri.method.reuse.CombineQueryAndCasesMethod
113 * @see jcolibri.method.revise.DefineNewIdsMethod
114 * @see jcolibri.method.retain.StoreCasesMethod
115 * 
116 */
117public class Test3 implements StandardCBRApplication {
118
119        Connector _connector;
120        CBRCaseBase _caseBase;
121        
122        /* (non-Javadoc)
123         * @see jcolibri.cbraplications.BasicCBRApplication#configure()
124         */
125        public void configure() throws ExecutionException{
126                try{
127                _connector = new DataBaseConnector();
128                _connector.initFromXMLfile(es.ucm.fdi.gaia.jcolibri.util.FileIO.findFile("es/ucm/fdi/gaia/jcolibri/test/test3/databaseconfig.xml"));
129                _caseBase  = new LinealCaseBase();
130                } catch (Exception e){
131                        throw new ExecutionException(e);
132                }
133        }
134
135        
136        /* (non-Javadoc)
137         * @see jcolibri.cbraplications.BasicCBRApplication#preCycle()
138         */
139        public CBRCaseBase preCycle() throws ExecutionException {
140                _caseBase.init(_connector);     
141                for(es.ucm.fdi.gaia.jcolibri.cbrcore.CBRCase c: _caseBase.getCases())
142                        System.out.println(c);
143                return _caseBase;
144        }
145        
146        /* (non-Javadoc)
147         * @see jcolibri.cbraplications.BasicCBRApplication#cycle()
148         */
149        public void cycle(CBRQuery query) throws ExecutionException 
150        {               
151                /********* NumericSim Retrieval **********/
152                
153                NNConfig simConfig = new NNConfig();
154                simConfig.setDescriptionSimFunction(new Average());
155                simConfig.addMapping(new Attribute("Accommodation", TravelDescription.class), new Equal());
156                Attribute duration = new Attribute("Duration", TravelDescription.class);
157                simConfig.addMapping(duration, new Interval(31));
158                simConfig.setWeight(duration, 0.5);
159                simConfig.addMapping(new Attribute("HolidayType", TravelDescription.class), new Equal());
160                simConfig.addMapping(new Attribute("NumberOfPersons", TravelDescription.class), new Equal());
161                simConfig.addMapping(new Attribute("Price", TravelDescription.class), new Interval(4000));
162                
163                simConfig.addMapping(new Attribute("Region",   TravelDescription.class), new Average());
164                simConfig.addMapping(new Attribute("region",   Region.class), new Equal());
165                simConfig.addMapping(new Attribute("city",     Region.class), new Equal());
166                simConfig.addMapping(new Attribute("airport",  Region.class), new Equal());
167                simConfig.addMapping(new Attribute("currency", Region.class), new Equal());
168
169                
170                System.out.println("Query:");
171                System.out.println(query);
172                System.out.println();
173                
174                
175                /********* Execute NN ************/
176                Collection<RetrievalResult> eval = NNScoringMethod.evaluateSimilarity(_caseBase.getCases(), query, simConfig);
177                
178                /********* Select cases **********/
179                Collection<CBRCase> selectedcases = SelectCases.selectTopK(eval, 1);
180                
181                /********* Reuse **********/
182                
183                //Combine query description with cases solutions, obtaining a list of new cases.
184                Collection<CBRCase> newcases = CombineQueryAndCasesMethod.combine(query, selectedcases);
185                System.out.println("Combined cases");
186                for(es.ucm.fdi.gaia.jcolibri.cbrcore.CBRCase c: newcases)
187                        System.out.println(c);
188                
189                /********* Revise **********/
190                // Lets store only the best case
191                CBRCase bestCase = newcases.iterator().next();
192                
193                // Define new ids for the compound attributes
194                HashMap<Attribute, Object> componentsKeys = new HashMap<Attribute,Object>();
195                componentsKeys.put(new Attribute("caseId",TravelDescription.class), "test3id"); 
196                componentsKeys.put(new Attribute("id",Region.class), 7);        
197                es.ucm.fdi.gaia.jcolibri.method.revise.DefineNewIdsMethod.defineNewIdsMethod(bestCase, componentsKeys);
198                
199                System.out.println("Cases with new Id");
200                System.out.println(bestCase);
201                
202                /********* Retain **********/
203                
204                // Uncomment next line to store cases into persistence
205                //jcolibri.method.retain.StoreCasesMethod.storeCase(_caseBase, bestCase);
206        }
207
208        /* (non-Javadoc)
209         * @see jcolibri.cbraplications.BasicCBRApplication#postCycle()
210         */
211        public void postCycle() throws ExecutionException {
212                this._caseBase.close();
213
214        }
215
216        /**
217         * @param args
218         */
219        public static void main(String[] args) {
220                // Launch DDBB manager
221                es.ucm.fdi.gaia.jcolibri.test.database.HSQLDBserver.init();
222
223                Test3 test3 = new Test3();
224                try {
225                        test3.configure();
226                        test3.preCycle();
227                        
228                        //BufferedReader reader  = new BufferedReader(new InputStreamReader(System.in));                        
229                        //do
230                        //{     
231                        
232                        /********* Query Definition **********/
233                        TravelDescription queryDesc = new TravelDescription();
234                        queryDesc.setAccommodation(TravelDescription.AccommodationTypes.ThreeStars);
235                        queryDesc.setDuration(7);
236                        queryDesc.setHolidayType("Recreation");
237                        queryDesc.setNumberOfPersons(2);
238                        queryDesc.setPrice(700);
239                        
240                        Region region = new Region();
241                        region.setRegion("Bulgaria");
242                        region.setCity("Sofia");
243                        region.setCurrency("Euro");
244                        region.setAirport("airport");
245                        queryDesc.setRegion(region);
246                        
247                        CBRQuery query = new CBRQuery();
248                        query.setDescription(queryDesc);
249                        
250                        test3.cycle(query);
251                        
252                        //      System.out.println("Cycle finished. Type exit to idem");
253                        //}while(!reader.readLine().equals("exit"));
254                        
255                        test3.postCycle();
256                        
257                        //Shutdown DDBB manager
258                        es.ucm.fdi.gaia.jcolibri.test.database.HSQLDBserver.shutDown();
259
260                } catch (ExecutionException e) {
261                        System.out.println(e.getMessage());
262                        e.printStackTrace();
263                } catch (Exception e) {
264                        // TODO Auto-generated catch block
265                        e.printStackTrace();
266                }
267        }
268
269}