/*
* This file is part of JGAP.
*
* JGAP offers a dual license model containing the LGPL as well as the MPL.
*
* For licensing information please see the file license.txt included with JGAP
* or have a look at the top of class org.jgap.Chromosome which representatively
* includes the JGAP license policy applicable for any file delivered with JGAP.
*/
package org.jgap.util;
import java.math.*;
import java.util.*;
/**
* Class used to help in the testing of the hashCode() method.
*
* @author John Serri
* @since 2.1
*/
public class TestHashcode {
/** String containing the CVS revision. Read out via reflection! */
private static final String CVS_REVISION = "$Revision: 1.8 $";
/**
* Determines if object should output debug information.
*/
private boolean m_verbose;
/**
* Minimum average value of hashCodes needed to pass the testDispersion()
* test
*
* @see TestHashcode#testDispersion, m_AverageMax
*/
private double m_AverageMin = 0.0d;
/**
* Maximum average value of hashCodes needed to pass the testDispersion()
* test
*
* @see TestHashcode#testDispersion, m_AverageMin
*/
private double m_AverageMax = 1.0d;
/**
* Minimum Standard Deviation value of hashCodes needed to pass the
* testDispersion() test
*
* @see testDispersion(), m_StdDevMax
*/
private double m_StdDevMin = 1.0d;
/**
* Maximum Standard Deviation value of hashCodes needed to pass the
* testDispersion() test
*
* @see testDispersion(), m_StdDevMin
*/
private double m_StdDevMax = 2.0d;
/**
* fraction of hashCodes that must be unique for the testHashCodeUniqueness
* method to succed.
*
* @see testHashCodeUniqueness
*/
private double m_fractionUnique = 0.9d;
/**
* Contains the real fraction of hashCodes that where found to be unique in
* testHashCodeUniqueness.
*/
private double m_actualFractionUnique = 0.0d;
/**
* Set whether the object will output debug information.
*
* @param a_verbose true if you want debug information, else set to false
*
* @since 2.1
*/
public void setVerbose(boolean a_verbose) {
m_verbose = a_verbose;
}
/**
* Set's the maximum average value of hashCodes needed to pass the
* testDispersion() test. Also see TestHascode#testDispersion.
*
* @param a_averageMax New Maximum average
*
*/
public void setAverageMax(double a_averageMax) {
m_AverageMax = a_averageMax;
}
/**
* Set's the minimum average value of hashCodes needed to pass the
* testDispersion() test
*
* @param a_averageMin new Minimum average
* @see TestHashcode#testDispersion
*/
public void setAverageMin(double a_averageMin) {
m_AverageMin = a_averageMin;
}
/**
* Set's the Maximum standard deviationvalue of hashCodes needed to pass
* the testDispersion() test
*
* @param a_stdDevMax new Maximum standard deviation
* @see TestHashcode#testDispersion
*
* @since 2.1
*/
public void setStdDevMax(double a_stdDevMax) {
m_StdDevMax = a_stdDevMax;
}
/**
* Set's the Minimum standard deviationvalue of hashCodes needed to pass
* the testDispersion() test
*
* @param a_stdDevMin new Minimum standard deviation
* @see TestHashcode#testDispersion
*
* @since 2.1
*/
public void setStdDevMin(double a_stdDevMin) {
m_StdDevMin = a_stdDevMin;
}
/**
* Set's the fraction of hashCodes that must be unique for the
* testHashCodeUniqueness method to succed.
*
* @param a_fractionUnique new value, must be between 0.0 and 1.0
* @throws IllegalArgumentException
* @see TestHashcode#testHashCodeUniqueness
*
* @since 2.1
*/
public void setFractionUnique(double a_fractionUnique) {
if ( (a_fractionUnique < 0.0) || (a_fractionUnique > 1.0)) {
throw new IllegalArgumentException(
"fractionUnique must be between 0.0 and 1.0");
}
m_fractionUnique = a_fractionUnique;
}
public double getActualFractionUnique() {
return m_actualFractionUnique;
}
/**
* Test that verifies that a the fraction of unique hashCodes is greater
* than the one specified.
*
* @param a_ObjectList list of objects to test
* @return true if the fraction of unique hashCodes is greater than the one
* specified. Else false
* @see TestHashcode#setFractionUnique
*
* @author John Serri
* @since 2.1
*/
public boolean testHashCodeUniqueness(List a_ObjectList) {
boolean result = false;
int index;
int newvalue;
int numObjects = a_ObjectList.size();
Hashtable hashCodes = new Hashtable();
Integer key;
for (index = 0; index < numObjects; index++) {
int hashcode = a_ObjectList.get(index).hashCode();
key = new Integer(hashcode);
if (hashCodes.containsKey(key)) {
newvalue = ( (Integer) hashCodes.get(key)).intValue() + 1;
hashCodes.put(key, new Integer(newvalue));
}
else {
hashCodes.put(key, new Integer(1));
}
}
m_actualFractionUnique = ( (double) hashCodes.size() / (double) numObjects);
if (m_actualFractionUnique < m_fractionUnique) {
result = false;
}
else {
result = true;
}
return result;
}
/**
* Test to make sure that equal objects all have the same hashCode.
*
* @param a_ObjectList list of objects to test
* @return true if all hashCodes in List are the same. Else false
*
* @author John Serri
* @since 2.1
*/
public boolean testHashCodeEquality(List a_ObjectList) {
int index;
int hashCode;
long numObjects = a_ObjectList.size();
if (numObjects < 2) {
return false;
}
hashCode = a_ObjectList.get(0).hashCode();
for (index = 1; index < numObjects; index++) {
if (hashCode != a_ObjectList.get(index).hashCode()) {
return false;
}
}
return true;
}
/**
* Test that verifies if average and Standard deviation of hashCodes in
* list match criteria.
*
* @param a_ObjectList list of objects to test
* @return true if average and Standard deviation of hashCodes in List
* match criterias. Else false
* @see TestHashcode#setAverageMax
* @see TestHashcode#setAverageMin
* @see TestHashcode#setStdDevMax
* @see TestHashcode#setStdDevMin
*
* @author John Serri
* @since 2.1
*/
public boolean testDispersion(List a_ObjectList) {
int index;
boolean result = false;
int[] hashCodes = new int[a_ObjectList.size()];
long numObjects = a_ObjectList.size();
double average = 0;
double stdDev;
double sumOfSquare;
double squareOfSum;
for (index = 0; index < numObjects; index++) {
hashCodes[index] = a_ObjectList.get(index).hashCode();
}
//Average
for (index = 0; index < numObjects; index++) {
average += hashCodes[index];
}
average /= numObjects;
//STD Deviation
sumOfSquare = 0;
squareOfSum = 0;
for (index = 0; index < numObjects; index++) {
sumOfSquare += (double) hashCodes[index]
* (double) hashCodes[index];
squareOfSum += hashCodes[index];
}
squareOfSum *= squareOfSum;
stdDev = (sumOfSquare * numObjects) - squareOfSum;
stdDev /= numObjects * (numObjects - 1);
stdDev = Math.sqrt(stdDev);
if (m_verbose) {
System.out.println("Average =" + average + " StdDev =" + stdDev);
System.out.println("Average - StdDev =" + (average - stdDev));
System.out.println("Average + StdDev =" + (average + stdDev));
}
if ( (m_AverageMin < average) && (average < m_AverageMax)) {
result = true;
}
else {
result = false;
}
if ( (m_StdDevMin < stdDev) && (stdDev < m_StdDevMax)) {
result &= true;
}
else {
result = false;
}
return result;
}
/**
* Simple main method to test the class.
*
* @param args ignored
*
* @author John Serri
* @since 2.1
*/
public static void main(String[] args) {
int com;
TestHashcode th = new TestHashcode();
List tl = new ArrayList();
for (com = 600000; com < 600100; com++) {
tl.add(new BigDecimal(com));
}
th.testDispersion(tl);
th.setFractionUnique(0.8);
th.testHashCodeUniqueness(tl);
}
}