compute Min Euclidean Distances - Java java.lang

Java examples for java.lang:Math Geometry Distance

Description

compute Min Euclidean Distances

Demo Code

/*//  www . jav a 2s  . c o  m
 *  Java Information Dynamics Toolkit (JIDT)
 *  Copyright (C) 2012, Joseph T. Lizier
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

public class Main{
    public static int MAX_TIMESTEPS_FOR_FAST_DISTANCE = 2000;
    public static double[] computeMinEuclideanDistances(
            double[][] observations) {
        if (observations.length <= MAX_TIMESTEPS_FOR_FAST_DISTANCE) {
            return EuclideanUtils
                    .computeMinEuclideanDistancesFast(observations);
        } else {
            return computeMinEuclideanDistancesNaive(observations);
        }
    }
    /**
     * Return the minimum Euclidean distance from each point to any other observation.
     * Computes this faster than using naive computation.
     * 
     * Exposed as a public method for debugging purposes only.
     * 
     * @param observations
     * @return
     */
    public static double[] computeMinEuclideanDistancesFast(
            double[][] observations) {

        int dimensions = observations[0].length;

        int timeSteps = observations.length;
        // Hold the sqr distance from index1 to index2 ...
        double[][] sqrDistance = new double[timeSteps][timeSteps];
        // ... computed over this many of the variables so far
        int[][] addedInUpToVariable = new int[timeSteps][timeSteps];
        double[] minDistance = new double[timeSteps];

        for (int t1 = 0; t1 < timeSteps; t1++) {
            // Current minimum distance from this index to another point:
            double minSqrDistance = Double.POSITIVE_INFINITY;

            // First grab the minimum distance from nodes for which the distance might
            //  have already been measured
            for (int t2 = 0; t2 < t1; t2++) {
                if (addedInUpToVariable[t2][t1] == dimensions) {
                    // We have previously computed this distance from t2 to t1
                    sqrDistance[t1][t2] = sqrDistance[t2][t1];
                    // unnecessary, since we won't be looking at [t1][t2] later:
                    addedInUpToVariable[t1][t2] = dimensions;
                    if (sqrDistance[t1][t2] < minSqrDistance) {
                        minSqrDistance = sqrDistance[t1][t2];
                    }
                }
            }
            // Now check the previously considered source nodes which didn't have their full distance
            //  computed in case we need to compute them
            for (int t2 = 0; t2 < t1; t2++) {
                if (addedInUpToVariable[t2][t1] != dimensions) {
                    // We have not finished computing this distance from t1
                    addedInUpToVariable[t1][t2] = addedInUpToVariable[t2][t1];
                    sqrDistance[t1][t2] = sqrDistance[t2][t1];
                    for (; (sqrDistance[t1][t2] < minSqrDistance)
                            && (addedInUpToVariable[t1][t2] < dimensions); addedInUpToVariable[t1][t2]++) {
                        double distOnThisVar = observations[t1][addedInUpToVariable[t1][t2]]
                                - observations[t2][addedInUpToVariable[t1][t2]];
                        sqrDistance[t1][t2] += distOnThisVar
                                * distOnThisVar;
                    }
                    if (sqrDistance[t1][t2] < minSqrDistance) {
                        // we finished the calculation and t2 is now the closest observation to t1
                        minSqrDistance = sqrDistance[t1][t2];
                    }
                }
            }
            // Now check any source nodes t2 for which there is no chance we've looked at the
            //  the distance back to t1 yet
            for (int t2 = t1 + 1; t2 < timeSteps; t2++) {
                for (; (sqrDistance[t1][t2] < minSqrDistance)
                        && (addedInUpToVariable[t1][t2] < dimensions); addedInUpToVariable[t1][t2]++) {
                    double distOnThisVar = observations[t1][addedInUpToVariable[t1][t2]]
                            - observations[t2][addedInUpToVariable[t1][t2]];
                    sqrDistance[t1][t2] += distOnThisVar * distOnThisVar;
                }
                if (sqrDistance[t1][t2] < minSqrDistance) {
                    // we finished the calculation and  t2 is now the closest observation to t1
                    minSqrDistance = sqrDistance[t1][t2];
                }
            }

            minDistance[t1] = Math.sqrt(minSqrDistance);
        }
        return minDistance;
    }
    /**
     * Naive method for computing minimum distance - slower but needs less memory.
     * Made public for debugging only. O(d.n^2) speed
     * 
     * @param observations
     * @return
     */
    public static double[] computeMinEuclideanDistancesNaive(
            double[][] observations) {
        int numObservations = observations.length;
        int dimensions = observations[0].length;
        double[] distances = new double[numObservations];
        for (int t = 0; t < numObservations; t++) {
            double minDistance = Double.POSITIVE_INFINITY;
            for (int t2 = 0; t2 < numObservations; t2++) {
                if (t == t2) {
                    continue;
                }
                double thisDistance = 0.0;
                for (int d = 0; (d < dimensions)
                        && (thisDistance < minDistance); d++) {
                    double distanceOnThisVar = (observations[t][d] - observations[t2][d]);
                    thisDistance += distanceOnThisVar * distanceOnThisVar;
                }
                // Now we need to sqrt the distance sum
                thisDistance = Math.sqrt(thisDistance);
                // Now check if this is a lower distance
                if (thisDistance < minDistance) {
                    minDistance = thisDistance;
                }
            }
            distances[t] = minDistance;
        }
        return distances;
    }
}

Related Tutorials