001 package jcolibri.test.test13.similarity; 002 003 import java.util.ArrayList; 004 import java.util.StringTokenizer; 005 006 import jcolibri.exception.NoApplicableSimilarityFunctionException; 007 import jcolibri.method.retrieve.NNretrieval.similarity.LocalSimilarityFunction; 008 009 /** 010 * This function converts the text value of an attribute into several numeric 011 * values and calculates its average. Then it computes the interval difference 012 * between query and case. 013 * <p> 014 * Example: 015 * <p> 016 * <p> 017 * Query attribute: 2.0, 4.0 -> Average = 3.0 018 * <p> 019 * Case attribute: 5.0, 9.0, 4.0 -> Average = 6.0 020 * <p> 021 * If interval param is 9.0 computed similarity equals: 0.33 022 */ 023 public class AverageMultipleTextValues implements LocalSimilarityFunction { 024 025 double _interval; 026 027 /** Creates a new instance of MaxString */ 028 public AverageMultipleTextValues(double interval) { 029 _interval = interval; 030 } 031 032 private double extractStringAverage(String s) { 033 ArrayList<Double> list = new ArrayList<Double>(); 034 StringTokenizer st = new StringTokenizer(s); 035 while (st.hasMoreTokens()) { 036 String num = st.nextToken(); 037 double dnum = 0; 038 try { 039 dnum = Double.parseDouble(num); 040 } catch (Exception e) { 041 } 042 if (dnum == 0) { 043 try { 044 dnum = (double) Integer.parseInt(num); 045 } catch (Exception e) { 046 } 047 } 048 list.add(new Double(dnum)); 049 } 050 051 double total = list.size(); 052 if (total == 0) 053 return 0; 054 055 double acum = 0; 056 for (Double Dnum : list) 057 { 058 acum += Dnum.doubleValue(); 059 } 060 return acum / total; 061 } 062 063 public double compute(Object caseObject, Object queryObject) throws NoApplicableSimilarityFunctionException 064 { 065 if ((caseObject == null) || (queryObject == null)) 066 return 0; 067 if (!(caseObject instanceof java.lang.String)) 068 throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), caseObject.getClass()); 069 if (!(queryObject instanceof java.lang.String)) 070 throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), queryObject.getClass()); 071 072 073 String caseS = (String) caseObject; 074 String queryS = (String) queryObject; 075 076 if (queryS.length() == 0) 077 return 0; 078 if (caseS.length() == 0) 079 return 0; 080 081 double qV = extractStringAverage(queryS); 082 double cV = extractStringAverage(caseS); 083 return 1 - (Math.abs(qV - cV) / _interval); 084 085 } 086 087 /** Applicable to String */ 088 public boolean isApplicable(Object o1, Object o2) 089 { 090 if((o1==null)&&(o2==null)) 091 return true; 092 else if(o1==null) 093 return o2 instanceof String; 094 else if(o2==null) 095 return o1 instanceof String; 096 else 097 return (o1 instanceof String)&&(o2 instanceof String); 098 } 099 100 101 }