Updating two metrics

This commit is contained in:
Marcel Kronfeld 2011-05-03 12:33:22 +00:00
parent ae46d9a3d7
commit 0438ee5055
2 changed files with 67 additions and 20 deletions

View File

@ -3,6 +3,7 @@ package eva2.server.go.operators.distancemetric;
import java.io.Serializable;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceDataTypeDouble;
/**
* The Euclidean metric just measures the Euclidean distance based on the default double representation
@ -13,28 +14,38 @@ import eva2.server.go.individuals.AbstractEAIndividual;
*
*/
public class EuclideanMetric implements InterfaceDistanceMetric, Serializable {
private boolean normedByDblRange = false;
public Object clone() {
return (Object) new EuclideanMetric(this);
}
public EuclideanMetric(EuclideanMetric a) {
this.setNormedByDblRange(a.isNormedByDblRange());
}
public EuclideanMetric() {
}
public EuclideanMetric(boolean normed) {
setNormedByDblRange(normed);
}
public double distance(AbstractEAIndividual indy1, AbstractEAIndividual indy2) {
double[] dIndy1, dIndy2;
double result = 0;
dIndy1 = AbstractEAIndividual.getDoublePositionShallow(indy1);
dIndy2 = AbstractEAIndividual.getDoublePositionShallow(indy2);
for (int i = 0; (i < dIndy1.length) && (i < dIndy2.length); i++) {
result += Math.pow((dIndy1[i] - dIndy2[i]), 2);
if (isNormedByDblRange()) {
double[][] range1 = ((InterfaceDataTypeDouble)indy1).getDoubleRange();
double[][] range2 = ((InterfaceDataTypeDouble)indy2).getDoubleRange();
return normedEuclideanDistance(dIndy1, range1, dIndy2, range2);
} else {
for (int i = 0; (i < dIndy1.length) && (i < dIndy2.length); i++) {
result += Math.pow((dIndy1[i] - dIndy2[i]), 2);
}
return Math.sqrt(result);
}
return Math.sqrt(result);
}
/**
@ -87,5 +98,15 @@ public class EuclideanMetric implements InterfaceDistanceMetric, Serializable {
public String getName() {
return "Euclidean Metric";
}
public void setNormedByDblRange(boolean normedByDblRange) {
this.normedByDblRange = normedByDblRange;
}
public boolean isNormedByDblRange() {
return normedByDblRange;
}
public String normedByDblRangeTipText() {
return "Set to true to norm the distance by the double range - only possible with InterfaceDataTypeDouble individuals.";
}
}

View File

@ -9,13 +9,16 @@ import eva2.tools.EVAERROR;
/**
* Define a metric on data stored within individuals, such as the personal best position
* in PSO.
* in PSO. The metric tries to set the stored data as double position to an indy clone.
* On these clones, the base metric is applied.
*
* @author mkron
*
*/
public class IndividualDataMetric implements InterfaceDistanceMetric, Serializable {
private String dataKey = ParticleSwarmOptimization.partBestPosKey;
private boolean normedDistance = true; // flag whether to use normed distances (for InterfaceDataTypeDouble)
// private boolean normedDistance = true; // flag whether to use normed distances (for InterfaceDataTypeDouble)
private InterfaceDistanceMetric baseMetric = new EuclideanMetric(true);
public IndividualDataMetric() {}
@ -23,7 +26,15 @@ public class IndividualDataMetric implements InterfaceDistanceMetric, Serializab
dataKey = key;
}
public IndividualDataMetric(IndividualDataMetric pBestMetric) {
public IndividualDataMetric(String key, InterfaceDistanceMetric bMetric) {
dataKey = key;
setBaseMetric(bMetric);
}
public IndividualDataMetric(IndividualDataMetric o) {
this.dataKey = o.dataKey;
// this.normedDistance = o.normedDistance;
this.setBaseMetric(o.getBaseMetric());
}
/** This method allows you to make a deep clone of
@ -40,11 +51,16 @@ public class IndividualDataMetric implements InterfaceDistanceMetric, Serializab
Object data1 = indy1.getData(dataKey);
Object data2 = indy2.getData(dataKey);
if (data1 instanceof double[] && (data2 instanceof double[])) {
if (normedDistance) {
double[][] range1 = ((InterfaceDataTypeDouble)indy1).getDoubleRange();
double[][] range2 = ((InterfaceDataTypeDouble)indy2).getDoubleRange();
return EuclideanMetric.normedEuclideanDistance((double[])data1, range1, (double[])data2, range2);
} else return EuclideanMetric.euclideanDistance((double[])data1, (double[])data2);
AbstractEAIndividual dataIndy1 = (AbstractEAIndividual) indy1.clone();
AbstractEAIndividual.setDoublePosition(dataIndy1, (double[]) data1);
AbstractEAIndividual dataIndy2 = (AbstractEAIndividual) indy2.clone();
AbstractEAIndividual.setDoublePosition(dataIndy2, (double[]) data2);
return getBaseMetric().distance(dataIndy1, dataIndy2);
// if (normedDistance) {
// double[][] range1 = ((InterfaceDataTypeDouble)indy1).getDoubleRange();
// double[][] range2 = ((InterfaceDataTypeDouble)indy2).getDoubleRange();
// return EuclideanMetric.normedEuclideanDistance((double[])data1, range1, (double[])data2, range2);
// } else return EuclideanMetric.euclideanDistance((double[])data1, (double[])data2);
} else {
EVAERROR.errorMsgOnce("Error, invalid key data, double array required by " + this.getClass().getName());
EVAERROR.errorMsgOnce("Using PhenotypeMetric as Backup...");
@ -67,14 +83,24 @@ public class IndividualDataMetric implements InterfaceDistanceMetric, Serializab
public String normedDistanceTipText() {
return "Flag whether to use euclidean distance directly or normed by the double range.";
}
public boolean isNormedDistance() {
return normedDistance;
}
public void setNormedDistance(boolean normedDistance) {
this.normedDistance = normedDistance;
}
// public boolean isNormedDistance() {
// return normedDistance;
// }
// public void setNormedDistance(boolean normedDistance) {
// this.normedDistance = normedDistance;
// }
public static String globalInfo() {
return "Uses individual object data (so far only double[]) to calculate the distance.";
}
public void setBaseMetric(InterfaceDistanceMetric baseMetric) {
this.baseMetric = baseMetric;
}
public InterfaceDistanceMetric getBaseMetric() {
return baseMetric;
}
public String baseMetricTipText() {
return "The metric to be used on the stored data objects.";
}
}