001 package jcolibri.method.retrieve.NNretrieval.similarity.local.recommenders; 002 003 import jcolibri.exception.NoApplicableSimilarityFunctionException; 004 import jcolibri.method.retrieve.NNretrieval.similarity.LocalSimilarityFunction; 005 006 007 008 /** 009 * This function returns the similarity of two numbers (or Enums) following 010 * the INRECA - More is Better formulae 011 * 012 * sim(c.a,q.a)= if(c.a > q.a) then 1 else jump * (1- (q.a - c.a) / q.a)) 013 * 014 * jump must be defined by the designer. 015 */ 016 public class InrecaMoreIsBetter implements LocalSimilarityFunction { 017 018 double jump; 019 020 /** 021 * Constructor. 022 */ 023 public InrecaMoreIsBetter(double jumpSimilarity) { 024 this.jump = jumpSimilarity; 025 } 026 027 /** 028 * Applies the similarity function. 029 * 030 * @param caseObject is a Number 031 * @param queryObject is a Number 032 * @return result of apply the similarity function. 033 */ 034 public double compute(Object caseObject, Object queryObject) throws NoApplicableSimilarityFunctionException{ 035 if ((caseObject == null) || (queryObject == null)) 036 return 0; 037 if (! ((caseObject instanceof java.lang.Number)||(caseObject instanceof Enum))) 038 throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), caseObject.getClass()); 039 if (! ((queryObject instanceof java.lang.Number)||(queryObject instanceof Enum))) 040 throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), queryObject.getClass()); 041 042 double caseValue; 043 double queryValue; 044 045 if(caseObject instanceof Number) 046 { 047 Number n1 = (Number) caseObject; 048 Number n2 = (Number) queryObject; 049 caseValue = n1.doubleValue(); 050 queryValue = n2.doubleValue(); 051 } 052 else 053 { 054 Enum enum1 = (Enum)caseObject; 055 Enum enum2 = (Enum)queryObject; 056 caseValue = enum1.ordinal(); 057 queryValue = enum2.ordinal(); 058 } 059 060 if(caseValue >= queryValue) 061 return 1; 062 063 else return jump * (1- ((queryValue - caseValue) / queryValue) ); 064 065 } 066 067 /** Applicable to any Number subinstance */ 068 public boolean isApplicable(Object o1, Object o2) 069 { 070 if((o1==null)&&(o2==null)) 071 return true; 072 else if(o1==null) 073 return (o2 instanceof Number)||(o2 instanceof Enum); 074 else if(o2==null) 075 return (o1 instanceof Number)||(o1 instanceof Enum); 076 else 077 return ((o1 instanceof Number)&&(o2 instanceof Number)) || 078 ((o1 instanceof Enum)&&(o2 instanceof Enum)); 079 } 080 081 }