001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021/* 022 * @(#)CachingKernel.java 0.1 00/01/20 023 * 024 * By Thomas Down <td2@sanger.ac.uk> 025 */ 026 027package org.biojava.stats.svm; 028 029import java.util.HashMap; 030import java.util.Map; 031 032/** 033 * <p> 034 * Caches the results of a nested kernel so that k(a, b) need only be calculated 035 * once. 036 * </p> 037 * 038 * <p> 039 * This kernel is thread-safe. However, care must be taken when setting the 040 * nested kernel that no other thread is retrieving values at the same time. 041 * This would cause a race condition in which the newly flushed cache may 042 * contain a value from the previous kernel. 043 * </p> 044 * 045 * @author Thomas Down 046 * @author Matthew Pocock 047 */ 048public class CachingKernel extends NestedKernel { 049 transient private Map cache; 050 051 public CachingKernel() { 052 } 053 054 public CachingKernel(SVMKernel k) { 055 super(k); 056 } 057 058 public void setNestedKernel(SVMKernel k) { 059 super.setNestedKernel(k); 060 if(cache == null) { 061 cache = new HashMap(); 062 } 063 cache.clear(); 064 } 065 066 public double evaluate(Object x, Object y) { 067 ObjectPair op = new ObjectPair(x, y); 068 Double d = null; 069 synchronized (cache) { 070 d = (Double) cache.get(op); 071 } 072 if (d == null) { 073 d = new Double(getNestedKernel().evaluate(x, y)); 074 synchronized (cache) { 075 cache.put(op, d); 076 } 077 } 078 return d.doubleValue(); 079 } 080 081 public String toString() { 082 return getNestedKernel().toString(); 083 } 084 085 private static class ObjectPair { 086 Object a; 087 Object b; 088 089 public ObjectPair(Object a, Object b) { 090 this.a = a; 091 this.b = b; 092 } 093 094 public boolean equals(Object x) { 095 if (! (x instanceof ObjectPair)) 096 return false; 097 ObjectPair op = (ObjectPair) x; 098 return ((op.a == a && op.b == b) || 099 (op.a == b && op.b == a)); 100 } 101 102 public int hashCode() { 103 return a.hashCode() + b.hashCode(); 104 } 105 } 106}