All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.barrybecker4.optimization.parameter.PermutedDistanceCalculator Maven / Gradle / Ivy

/** Copyright by Barry G. Becker, 2000-2011. Licensed under MIT License: http://www.opensource.org/licenses/MIT  */
package com.barrybecker4.optimization.parameter;

import com.barrybecker4.optimization.parameter.types.Parameter;

import java.util.LinkedList;
import java.util.List;

/**
 *  Finds the distance between two PermutedParameterArrays.
 *
 *  @author Barry Becker
 */
public class PermutedDistanceCalculator  {

    /**
     * The distance computation will be quite different for this than a regular parameter array.
     * We want the distance to represent a measure of the amount of similarity between two permutations.
     * If there are similar runs between two permutations, then the distance should be relatively small.
     * N^2 operation, where N is the number of params.
     * @param pa1 first parameter array
     * @param pa2 second parameter array
     * @return the distance between this parameter array and another.
     */
    public double findDistance(PermutedParameterArray pa1, PermutedParameterArray pa2)  {
        assert (pa1.size() == pa2.size());

        ParameterArray paReverse = pa2.reverse();
        return Math.min(difference(pa1, pa2), difference(pa1, paReverse));
    }

    /**
     * The amount of difference can be used as a measure of distance
     * @return the amount of difference between pa and ourselves.
     */
    private double difference(ParameterArray pa1, ParameterArray pa2)  {

        List runLengths = new LinkedList<>();
        int len = pa1.size();
        int i = 0;

        while (i < len) {
            int runLength = determineRunLength(pa1, pa2, len, i, runLengths);
            i += runLength;
        }
        return calcDistance(pa1, runLengths);
    }

    /**
     * Adds the computed runlength to the runLengths list.
     * @return the computed runlength
     */
    private int determineRunLength(ParameterArray pa1, ParameterArray pa2, int len, int i, List runLengths) {
        int k;
        int ii = i;
        k = 1;
        int j = findCorrespondingEntryIndex(pa2, len, pa1.get(i));

        boolean matchFound = false;
        boolean matched;
        do {
            ii = ++ii % len;
            j = ++j % len;
            k++;
            matched = pa1.get(ii).equals(pa2.get(j));
            matchFound |= matched;
        } while (matched && k<=len);

        int runLength = k-1;

        if (matchFound) {
            runLengths.add(runLength);
        }
        return runLength;
    }

    /**
     * @return  the entry in pa that corresponds to param.
     * @throws AssertionError if not there. It must be there.
     */
    private int findCorrespondingEntryIndex(ParameterArray pa, int len, Parameter param) {
        int j=0;
        while (j runLengths) {

        // careful this could overflow if the run is really long.
        // If it does we may need to switch to BigInteger.
        double max = Math.pow(2, pa1.size());

        if (runLengths.isEmpty()) return max;

        double denom = 0;
        for (int run : runLengths) {
           denom += Math.pow(2, run-1);
        }
        return max / denom - 2.0;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy