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 int 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 IntLSHSketcher<OBJECT> implements Sketcher<OBJECT, int[]> {
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 IntLSHSketcher(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 IntLSHSketcher(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 IntLSHSketcher(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 int[] createSketch(OBJECT input) {
101                final int nele = arrayLength();
102                final int[] sketch = new int[nele];
103
104                for (int i = 0, j = 0; i < nele; i++) {
105                        for (int k = 0; k < Integer.SIZE; k++) {
106                                final int hash = hashFunctions.get(j++).computeHashCode(input);
107
108                                sketch[i] = (int) (sketch[i] | ((int) 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 int array of packed bits.
126         * 
127         * @return the number of ints that will be returned.
128         */
129        public int arrayLength() {
130                return (int) Math.ceil((double) hashFunctions.size() / Integer.SIZE);
131        }
132}