001/*
002        AUTOMATICALLY GENERATED BY jTemp FROM
003        /Users/jsh2/Work/openimaj/target/checkout/machine-learning/nearest-neighbour/src/main/jtemp/org/openimaj/lsh/functions/#T#PStableFactory.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.functions;
035
036import org.openimaj.citation.annotation.Reference;
037import org.openimaj.citation.annotation.ReferenceType;
038import org.openimaj.util.array.SparseIntArray;
039import org.openimaj.util.array.SparseIntArray.Entry;
040
041import cern.jet.random.engine.MersenneTwister;
042
043/**
044 * Base class for hashing schemes based on P-Stable distributions. The hash
045 * functions are of the form h(x) = floor((ax + b) / w).
046 * 
047 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
048 */
049 @Reference(
050        type = ReferenceType.Inproceedings,
051        author = { "Datar, Mayur", "Immorlica, Nicole", "Indyk, Piotr", "Mirrokni, Vahab S." },
052        title = "Locality-sensitive hashing scheme based on p-stable distributions",
053        year = "2004",
054        booktitle = "Proceedings of the twentieth annual symposium on Computational geometry",
055        pages = { "253", "", "262" },
056        url = "http://doi.acm.org/10.1145/997817.997857",
057        publisher = "ACM",
058        series = "SCG '04"
059)
060public abstract class IntPStableFactory extends IntHashFunctionFactory {
061        protected abstract class PStableFunction extends IntHashFunction {
062                protected double[] r;
063                protected double b;
064
065                PStableFunction(MersenneTwister rng) {
066                        super(rng);
067                }
068
069                @Override
070                public final int computeHashCode(int[] point) {
071                        double val = 0;
072                        for (int i = 0; i < point.length; i++) {
073                                val += point[i] * r[i];
074                        }
075
076                        val = (val + b) / w;
077
078                        return (int) Math.floor(val);
079                }
080                
081                @Override
082                public int computeHashCode(SparseIntArray array) {
083                        double val = 0;
084                        
085                        for (Entry e : array.entries()) {
086                                val += e.value * r[e.index];
087                        }
088                        
089                        val = (val + b) / w;
090
091                        return (int) Math.floor(val);                   
092                }
093        }
094
095        double w;
096
097        /**
098         * Construct with the given parameters.
099         * 
100         * @param ndims
101         *            number of dimensions of the data
102         * @param rng
103         *            the random number generator
104         * @param w
105         *            the width parameter
106         */
107        public IntPStableFactory(int ndims, MersenneTwister rng, double w) {
108                super(ndims, rng);
109
110                this.w = w;
111        }
112}