001/* 002 AUTOMATICALLY GENERATED BY jTemp FROM 003 /Users/jon/Work/openimaj/tags/openimaj-1.3.1/machine-learning/nearest-neighbour/src/main/jtemp/org/openimaj/lsh/sketch/#T#LSHSketcher.jtemp 004*/ 005/** 006 * Copyright (c) 2011, The University of Southampton and the individual contributors. 007 * All rights reserved. 008 * 009 * Redistribution and use in source and binary forms, with or without modification, 010 * are permitted provided that the following conditions are met: 011 * 012 * * Redistributions of source code must retain the above copyright notice, 013 * this list of conditions and the following disclaimer. 014 * 015 * * Redistributions in binary form must reproduce the above copyright notice, 016 * this list of conditions and the following disclaimer in the documentation 017 * and/or other materials provided with the distribution. 018 * 019 * * Neither the name of the University of Southampton nor the names of its 020 * contributors may be used to endorse or promote products derived from this 021 * software without specific prior written permission. 022 * 023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 025 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 026 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 027 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 028 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 030 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 032 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 033 */ 034package org.openimaj.lsh.sketch; 035 036import java.util.ArrayList; 037import java.util.List; 038 039import org.openimaj.util.hash.HashFunction; 040import org.openimaj.util.hash.HashFunctionFactory; 041import org.openimaj.util.sketch.Sketcher; 042 043/** 044 * A {@link Sketcher} that produces bit-string sketches encoded as byte arrays. 045 * Only the least-significant bit of each hash function will be appended to the 046 * final sketch. The length of the output array will be computed such that the 047 * bit from each hash function is contained. 048 * 049 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 050 * 051 * @param <OBJECT> 052 * Type of object being sketched 053 */ 054public class ByteLSHSketcher<OBJECT> implements Sketcher<OBJECT, byte[]> { 055 List<HashFunction<OBJECT>> hashFunctions; 056 057 /** 058 * Construct with the given functions. 059 * 060 * @param functions 061 * the underlying hash functions. 062 */ 063 public ByteLSHSketcher(List<HashFunction<OBJECT>> functions) { 064 this.hashFunctions = functions; 065 } 066 067 /** 068 * Construct with the given functions. 069 * 070 * @param first 071 * the first function 072 * @param remainder 073 * the remainder of the functions 074 */ 075 public ByteLSHSketcher(HashFunction<OBJECT> first, HashFunction<OBJECT>... remainder) { 076 this.hashFunctions = new ArrayList<HashFunction<OBJECT>>(); 077 this.hashFunctions.add(first); 078 079 for (final HashFunction<OBJECT> r : remainder) 080 this.hashFunctions.add(r); 081 } 082 083 /** 084 * Construct with the factory which is used to produce the required number 085 * of functions. 086 * 087 * @param factory 088 * the factory to use to produce the underlying hash functions. 089 * @param nFuncs 090 * the number of functions to create for the composition 091 */ 092 public ByteLSHSketcher(HashFunctionFactory<OBJECT> factory, int nFuncs) { 093 this.hashFunctions = new ArrayList<HashFunction<OBJECT>>(); 094 095 for (int i = 0; i < nFuncs; i++) 096 hashFunctions.add(factory.create()); 097 } 098 099 @Override 100 public byte[] createSketch(OBJECT input) { 101 final int nele = arrayLength(); 102 final byte[] sketch = new byte[nele]; 103 104 for (int i = 0, j = 0; i < nele; i++) { 105 for (int k = 0; k < Byte.SIZE; k++) { 106 final int hash = hashFunctions.get(j++).computeHashCode(input); 107 108 sketch[i] = (byte) (sketch[i] | ((byte) hash << k)); 109 } 110 } 111 112 return sketch; 113 } 114 115 /** 116 * Get the length of the sketch in bits. 117 * 118 * @return the number of bits in the sketch 119 */ 120 public int bitLength() { 121 return hashFunctions.size(); 122 } 123 124 /** 125 * Get the length of the output byte array of packed bits. 126 * 127 * @return the number of bytes that will be returned. 128 */ 129 public int arrayLength() { 130 return (int) Math.ceil((double) hashFunctions.size() / Byte.SIZE); 131 } 132}