diff --git a/src/eva2/server/go/operators/distancemetric/EuclideanMetric.java b/src/eva2/server/go/operators/distancemetric/EuclideanMetric.java index 2c77020b..45192d1e 100644 --- a/src/eva2/server/go/operators/distancemetric/EuclideanMetric.java +++ b/src/eva2/server/go/operators/distancemetric/EuclideanMetric.java @@ -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."; + } } diff --git a/src/eva2/server/go/operators/distancemetric/IndividualDataMetric.java b/src/eva2/server/go/operators/distancemetric/IndividualDataMetric.java index 949c0be8..2e8f6879 100644 --- a/src/eva2/server/go/operators/distancemetric/IndividualDataMetric.java +++ b/src/eva2/server/go/operators/distancemetric/IndividualDataMetric.java @@ -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."; + } }