From bb04ff223187df4369e546936d06e16dfa893c85 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Fri, 11 Dec 2015 12:14:35 +0100 Subject: [PATCH] Improve tests in Mathematics refs #53 --- .../individuals/InterfaceESIndividual.java | 2 +- .../operator/moso/MOSONoConvert.java | 2 +- .../statistics/StatisticalEvaluation.java | 2 +- .../java/eva2/tools/math/Mathematics.java | 49 ++++++-------- .../resources/html/DifferentialEvolution.html | 12 ++++ .../java/eva2/tools/math/MathematicsTest.java | 64 +++++++++++++++++-- 6 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 src/main/resources/html/DifferentialEvolution.html diff --git a/src/main/java/eva2/optimization/individuals/InterfaceESIndividual.java b/src/main/java/eva2/optimization/individuals/InterfaceESIndividual.java index 3e814457..673e0bf7 100644 --- a/src/main/java/eva2/optimization/individuals/InterfaceESIndividual.java +++ b/src/main/java/eva2/optimization/individuals/InterfaceESIndividual.java @@ -2,7 +2,7 @@ package eva2.optimization.individuals; /** * This interface gives access to a real-valued genotype and should - * only be used by mutation and crossover operators. Onyl exception are + * only be used by mutation and crossover operators. Only exception are * data type specific optimization strategies like PSO or DE. */ public interface InterfaceESIndividual { diff --git a/src/main/java/eva2/optimization/operator/moso/MOSONoConvert.java b/src/main/java/eva2/optimization/operator/moso/MOSONoConvert.java index 7dfd44ae..48bd2de1 100644 --- a/src/main/java/eva2/optimization/operator/moso/MOSONoConvert.java +++ b/src/main/java/eva2/optimization/operator/moso/MOSONoConvert.java @@ -24,7 +24,7 @@ public class MOSONoConvert implements InterfaceMOSOConverter, java.io.Serializab /** * This method takes a population of individuals with an array of * fitness values and calculates a single fitness value to replace - * the former fitness array. Please note: The orignal fitness values + * the former fitness array. Please note: The original fitness values * are lost this way, so please use the individual.setData() method * if you still want to access the original fitness values. * diff --git a/src/main/java/eva2/optimization/statistics/StatisticalEvaluation.java b/src/main/java/eva2/optimization/statistics/StatisticalEvaluation.java index b1a24fbc..0439d10d 100644 --- a/src/main/java/eva2/optimization/statistics/StatisticalEvaluation.java +++ b/src/main/java/eva2/optimization/statistics/StatisticalEvaluation.java @@ -198,7 +198,7 @@ public class StatisticalEvaluation { double[] dat = job1.getDoubleDataColumn(field); double median = Double.NaN; if (dat != null) { - median = Mathematics.median2(dat, true); + median = Mathematics.median(dat, true); median = StatisticalEvaluation.formatOutput(median); } diff --git a/src/main/java/eva2/tools/math/Mathematics.java b/src/main/java/eva2/tools/math/Mathematics.java index 2d0ca16a..5ee8d425 100644 --- a/src/main/java/eva2/tools/math/Mathematics.java +++ b/src/main/java/eva2/tools/math/Mathematics.java @@ -475,8 +475,9 @@ public final class Mathematics { * Check whether the given value lies within the interval in every * dimension. * - * @param x - * @param range + * @param v Value + * @param lower Lower bound + * @param upper Upper bound * @return true if the vector lies within the range, else false */ public static boolean isInRange(double v, double lower, double upper) { @@ -507,8 +508,8 @@ public final class Mathematics { * @return */ public static boolean isValidVec(double[][] d) { - for (int i = 0; i < d.length; i++) { - if (!isValidVector(d[i])) { + for (double[] vec : d) { + if (!isValidVector(vec)) { return false; } } @@ -621,16 +622,18 @@ public final class Mathematics { in = x; } - if (in.length == 1) { + Arrays.sort(in); + if (in.length == 0) { + return Double.NaN; + } else if (in.length == 1) { return in[0]; } else if (in.length == 2) { return (in[0] + in[1]) / 2.; } else { - Arrays.sort(in); - if (in.length % 2 != 0) { - return in[(in.length - 1) / 2]; + if (in.length % 2 == 1) { + return in[in.length / 2]; } else { - return (in[in.length / 2] + in[(in.length / 2) + 1]) / 2.; + return (in[in.length / 2 - 1] + in[in.length / 2]) / 2.; } } } @@ -663,21 +666,6 @@ public final class Mathematics { } } - - public static double median2(double[] vector, boolean clone) { - double[] in; - if (clone) { - in = vector.clone(); - } else { - in = vector; - } - if (in.length == 0) { - return 0; - } - Arrays.sort(in); - return in[(int) Math.floor(((double) in.length) / 2.0)]; - } - public static double variance(double[] vector) { double mean = Mathematics.mean(vector); double result = 0.0; @@ -787,7 +775,7 @@ public final class Mathematics { } /** - * Normalize the given vector to an euclidian length of 1. + * Normalize the given vector to a euclidean length of 1. * * @param v * @return @@ -797,7 +785,7 @@ public final class Mathematics { } /** - * Normalize the given vector to an euclidian length of 1. + * Normalize the given vector to a euclidean length of 1. * * @param v * @return @@ -943,7 +931,7 @@ public final class Mathematics { if ((val + step) < min) { return (2 * min - val - step); } - return (val += step); + return val + step; } /** @@ -954,7 +942,7 @@ public final class Mathematics { * * @param x A vector * @param y The reference vector - * @param def The default value to be use to avoid division by zero. + * @param def The default value to be used to avoid division by zero. * @return The relative distance of x to y. * @throws Exception */ @@ -1183,7 +1171,6 @@ public final class Mathematics { * @return the sum of the elements */ public static int sum(int[] ints) { - int sum = 0; for (int value : ints) { @@ -1208,8 +1195,8 @@ public final class Mathematics { /** * Add each entry of a vector with a scalar in a result vector. * - * @param s - * @param v + * @param s Scalar + * @param v Vector * @return */ public static void svAdd(double s, double[] v, double[] res) { diff --git a/src/main/resources/html/DifferentialEvolution.html b/src/main/resources/html/DifferentialEvolution.html new file mode 100644 index 00000000..036d34f7 --- /dev/null +++ b/src/main/resources/html/DifferentialEvolution.html @@ -0,0 +1,12 @@ + + +Differential Evolution - DE + + +

Differential Evolution - DE

+
+

+Description of DE. +
+ + \ No newline at end of file diff --git a/src/test/java/eva2/tools/math/MathematicsTest.java b/src/test/java/eva2/tools/math/MathematicsTest.java index dc2cbcd3..ca79cacb 100644 --- a/src/test/java/eva2/tools/math/MathematicsTest.java +++ b/src/test/java/eva2/tools/math/MathematicsTest.java @@ -2,7 +2,10 @@ package eva2.tools.math; import org.junit.Test; +import java.util.Arrays; + import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class MathematicsTest { @@ -26,6 +29,9 @@ public class MathematicsTest { public void testMean() throws Exception { double[] vals = {2.0,3.05,4.9,7.8,12.7}; assertEquals(6.09, Mathematics.mean(vals), 0.0); + + // Empty vector + assertEquals(0.0, Mathematics.mean(new double[]{}), 0.0); } @Test @@ -57,12 +63,29 @@ public class MathematicsTest { @Test public void testMedian() throws Exception { + // Handle empty case + assertEquals(Double.NaN, Mathematics.median(new double[]{}, true), 0.0); - } + // Median of single element array + assertEquals(2.4, Mathematics.median(new double[]{2.4}, true), 10E-6); - @Test - public void testMedian2() throws Exception { + // Median of two element array + assertEquals(5.0, Mathematics.median(new double[]{2.5, 7.5}, true), 10E-6); + // Median of even length array + double[] values = {9.8, 7.8, 8.6, 5.6, 3.2, 10.9}; + assertEquals(8.2, Mathematics.median(values, true), 10E-6); + + + // Median of odd length array + double[] values2 = {9.8, 7.8, 5.6, 3.2, 10.9}; + assertEquals(7.8, Mathematics.median(values2, false), 10E-6); + + // Median while preserving original array + double[] unsortedValues = {5.2, 3.4}; + double[] unsortedValues2 = {5.2, 3.4}; + Mathematics.median(unsortedValues, true); + assertTrue(Arrays.equals(unsortedValues, unsortedValues2)); } @Test @@ -103,11 +126,23 @@ public class MathematicsTest { @Test public void testSum() throws Exception { + // Array of doubles double[] values = {1.9,2.8,3.7,4.6,5.5}; - assertEquals(18.5, Mathematics.sum(values), 0.0); + + // Array of ints + int[] intValues = {1,9,2,8,3,7,4,6,5}; + assertEquals(45, Mathematics.sum(intValues)); } + @Test + public void testNorm() throws Exception { + double[] values = {3.0, 4.0}; + + assertEquals(5.0, Mathematics.norm(values), 0.0); + } + + @Test public void testScale() throws Exception { @@ -120,4 +155,25 @@ public class MathematicsTest { assertEquals(-4.05593, Mathematics.tTestEqSizeEqVar(values1, values2), 0.00001); } + + @Test + public void testProduct() throws Exception { + double[] values = {3.0, 4.0, 5.0}; + + assertEquals(60.0, Mathematics.product(values), 0.0); + } + + @Test + public void testIsInRange() throws Exception { + // Single dimension + assertTrue(Mathematics.isInRange(4.9, 1.2, 7.6)); + assertFalse(Mathematics.isInRange(0.0, 1.2, 3.4)); + + // Multidimensional + double[][] ranges = {{1.2, 7.6}, {1.2, 3.4}}; + assertTrue(Mathematics.isInRange(new double[]{4.9, 2.2}, ranges)); + assertFalse(Mathematics.isInRange(new double[]{9.9, 2.2}, ranges)); + } + + } \ No newline at end of file