001/*
002        AUTOMATICALLY GENERATED BY jTemp FROM
003        /Users/jsh2/Work/openimaj/target/checkout/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 short 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 ShortLSHSketcher<OBJECT> implements Sketcher<OBJECT, short[]> {
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 ShortLSHSketcher(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        @SafeVarargs
076        public ShortLSHSketcher(HashFunction<OBJECT> first, HashFunction<OBJECT>... remainder) {
077                this.hashFunctions = new ArrayList<HashFunction<OBJECT>>();
078                this.hashFunctions.add(first);
079
080                for (final HashFunction<OBJECT> r : remainder)
081                        this.hashFunctions.add(r);
082        }
083
084        /**
085         * Construct with the factory which is used to produce the required number
086         * of functions.
087         * 
088         * @param factory
089         *            the factory to use to produce the underlying hash functions.
090         * @param nFuncs
091         *            the number of functions to create for the composition
092         */
093        public ShortLSHSketcher(HashFunctionFactory<OBJECT> factory, int nFuncs) {
094                this.hashFunctions = new ArrayList<HashFunction<OBJECT>>();
095
096                for (int i = 0; i < nFuncs; i++)
097                        hashFunctions.add(factory.create());
098        }
099
100        @Override
101        public short[] createSketch(OBJECT input) {
102                final int nele = arrayLength();
103                final short[] sketch = new short[nele];
104
105                for (int i = 0, j = 0; i < nele; i++) {
106                        for (int k = 0; k < Short.SIZE; k++) {
107                                final int hash = hashFunctions.get(j++).computeHashCode(input);
108
109                                sketch[i] = (short) (sketch[i] | ((short) hash << k));
110                        }
111                }
112
113                return sketch;
114        }
115
116        /**
117         * Get the length of the sketch in bits.
118         * 
119         * @return the number of bits in the sketch
120         */
121        public int bitLength() {
122                return hashFunctions.size();
123        }
124
125        /**
126         * Get the length of the output short array of packed bits.
127         * 
128         * @return the number of shorts that will be returned.
129         */
130        public int arrayLength() {
131                return (int) Math.ceil((double) hashFunctions.size() / Short.SIZE);
132        }
133}