From bb04ff223187df4369e546936d06e16dfa893c85 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Fri, 11 Dec 2015 12:14:35 +0100 Subject: [PATCH 1/9] 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 From a156eb0f23fdf190c502d73a1d3186bb5481a368 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Fri, 11 Dec 2015 12:25:54 +0100 Subject: [PATCH 2/9] Upgrade to JUnit 4.12 refs #53 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a7d6012f..722716b9 100644 --- a/build.gradle +++ b/build.gradle @@ -29,5 +29,5 @@ dependencies { compile group: 'javax.help', name: 'javahelp', version: '2.0.05' compile group: 'org.yaml', name: 'snakeyaml', version: '1.16' compile group: 'gov.nist.math', name: 'jama', version: '1.0.3' - testCompile group: 'junit', name: 'junit', version: '4.11' + testCompile group: 'junit', name: 'junit', version: '4.12' } From 0cb1c875d96c7c01e7286fd38aaf3d3da95eff8a Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Fri, 11 Dec 2015 15:53:08 +0100 Subject: [PATCH 3/9] More Math tests refs #53 --- .../java/eva2/tools/math/Mathematics.java | 19 ++--- .../java/eva2/tools/math/MathematicsTest.java | 78 +++++++++++++++---- 2 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/main/java/eva2/tools/math/Mathematics.java b/src/main/java/eva2/tools/math/Mathematics.java index 5ee8d425..94491398 100644 --- a/src/main/java/eva2/tools/math/Mathematics.java +++ b/src/main/java/eva2/tools/math/Mathematics.java @@ -389,8 +389,8 @@ public final class Mathematics { /** * Intersect two ranges resulting in the maximum range contained in both. * - * @param modRange - * @param makeRange + * @param r1 + * @param r2 * @param destRange */ public static void intersectRange(double[][] r1, double[][] r2, @@ -538,6 +538,8 @@ public final class Mathematics { } /** + * Linear interpolation between two points + * * @param f0 * @param f1 * @param t @@ -553,7 +555,7 @@ public final class Mathematics { * * @param x The argument at the point with unknown function value * @param x0 The argument at the last position with a function value - * @param x1 The argument at the next known fuction value + * @param x1 The argument at the next known function value * @param f0 The function value at the position x0 * @param f1 The function value at the position x1 * @return The function value at position x given by linear interpolation. @@ -1214,9 +1216,7 @@ public final class Mathematics { */ public static double[] svDiv(double s, double[] v) { double[] res = new double[v.length]; - for (int i = 0; i < v.length; i++) { - res[i] = v[i] / s; - } + svDiv(s, v, res); return res; } @@ -1243,9 +1243,7 @@ public final class Mathematics { */ public static double[] svMult(double s, double[] v) { double[] res = new double[v.length]; - for (int i = 0; i < v.length; i++) { - res[i] = v[i] * s; - } + svMult(s, v, res); return res; } @@ -1254,7 +1252,6 @@ public final class Mathematics { * * @param s a scalar * @param v an array to be multiplied with s. - * @return a scaled array. */ public static void svMult(double s, double[] v, double[] res) { for (int i = 0; i < v.length; i++) { @@ -1265,7 +1262,7 @@ public final class Mathematics { /** * Add vectors scaled: res[i] = s*v[i] + w[i] * - * @param s + * @param s Scaling factor * @param v * @param w * @return diff --git a/src/test/java/eva2/tools/math/MathematicsTest.java b/src/test/java/eva2/tools/math/MathematicsTest.java index ca79cacb..20c704d2 100644 --- a/src/test/java/eva2/tools/math/MathematicsTest.java +++ b/src/test/java/eva2/tools/math/MathematicsTest.java @@ -4,9 +4,7 @@ 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; +import static org.junit.Assert.*; public class MathematicsTest { @@ -21,13 +19,13 @@ public class MathematicsTest { @Test public void testMax() throws Exception { - double[] vals = {1,2,3,4,5,6,4,3,2,2,12}; + double[] vals = {1, 2, 3, 4, 5, 6, 4, 3, 2, 2, 12}; assertEquals(12.0, Mathematics.max(vals), 0.0); } @Test public void testMean() throws Exception { - double[] vals = {2.0,3.05,4.9,7.8,12.7}; + double[] vals = {2.0, 3.05, 4.9, 7.8, 12.7}; assertEquals(6.09, Mathematics.mean(vals), 0.0); // Empty vector @@ -44,7 +42,9 @@ public class MathematicsTest { @Test public void testContains() throws Exception { - assertTrue(Mathematics.contains(new int[]{1,2,3,4,5}, 4)); + assertTrue(Mathematics.contains(new int[]{1, 2, 3, 4, 5}, 4)); + + assertFalse(Mathematics.contains(new int[]{1, 2, 3, 4, 5}, 9)); } @Test @@ -90,14 +90,14 @@ public class MathematicsTest { @Test public void testVariance() throws Exception { - double[] values = {9.8,9.2,12.3,15.7,3.14}; + double[] values = {9.8, 9.2, 12.3, 15.7, 3.14}; assertEquals(21.37892, Mathematics.variance(values), 0.000001); } @Test public void testStdDev() throws Exception { - double[] values = {12.9,13.5,19.8,12.3,10.7}; + double[] values = {12.9, 13.5, 19.8, 12.3, 10.7}; // Mean assertEquals(13.84, Mathematics.mean(values), 0.000001); @@ -109,7 +109,7 @@ public class MathematicsTest { @Test public void testMin() throws Exception { - double[] values = {1.9,2.8,3.7,4.6,5.5}; + double[] values = {1.9, 2.8, 3.7, 4.6, 5.5}; assertEquals(1.9, Mathematics.min(values), 0.0); } @@ -127,11 +127,11 @@ public class MathematicsTest { @Test public void testSum() throws Exception { // Array of doubles - double[] values = {1.9,2.8,3.7,4.6,5.5}; + 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}; + int[] intValues = {1, 9, 2, 8, 3, 7, 4, 6, 5}; assertEquals(45, Mathematics.sum(intValues)); } @@ -145,13 +145,15 @@ public class MathematicsTest { @Test public void testScale() throws Exception { - + double[] values = {1.0, 2.0, 3.0}; + Mathematics.scale(2, values); + assertArrayEquals(new double[]{2.0, 4.0, 6.0}, values, 0.0); } @Test public void testTTestEqSizeEqVar() { - double[] values1 = {6,6,2,7,8,8,2,3,5,7,10,5,4,7,5,7,4,5,2,5,3,4,4,4,4}; - double[] values2 = {6,11,8,5,11,8,10,7,4,3,7,6,10,10,6,5,10,11,13,8,5,11,7,8,5}; + double[] values1 = {6, 6, 2, 7, 8, 8, 2, 3, 5, 7, 10, 5, 4, 7, 5, 7, 4, 5, 2, 5, 3, 4, 4, 4, 4}; + double[] values2 = {6, 11, 8, 5, 11, 8, 10, 7, 4, 3, 7, 6, 10, 10, 6, 5, 10, 11, 13, 8, 5, 11, 7, 8, 5}; assertEquals(-4.05593, Mathematics.tTestEqSizeEqVar(values1, values2), 0.00001); } @@ -175,5 +177,53 @@ public class MathematicsTest { assertFalse(Mathematics.isInRange(new double[]{9.9, 2.2}, ranges)); } + @Test + public void testInverse() throws Exception { + double[][] matrix = {{4.0, 3.0}, {3.0, 2.0}}; + double[][] inverseMatrix = {{-2.0, 3.0}, {3.0, -4.0}}; + double[][] result = Mathematics.inverse(matrix); + for (int i = 0; i < result.length; i++) { + assertArrayEquals(inverseMatrix[i], result[i], 0.0); + } + + // Non square matrix + assertNull(Mathematics.inverse(new double[][]{{1.0, 2.0}})); + + // Null matrix + assertNull(Mathematics.inverse(null)); + + // Matrix with determinant = 0 + assertNull(Mathematics.inverse(new double[][]{ + {1.0, 4.0, 5.0}, + {2.0, 5.0, 7.0}, + {3.0, 6.0, 9.0} + })); + } + + @Test + public void testDeterminant() throws Exception { + // 3x3 Matrix with determinant 0 + assertEquals(0.0, Mathematics.determinant(new double[][]{ + {1.0, 4.0, 5.0}, + {2.0, 5.0, 7.0}, + {3.0, 6.0, 9.0} + }), 0.0); + } + + @Test + public void testLinearInterpolation() throws Exception { + // Find x = 2.0 for x0(1,1) and x1(3,3) + assertEquals(2.0, Mathematics.linearInterpolation(2.0, 1.0, 3.0, 1.0, 3.0), 0.0); + + // If x0 and x1 are the same we can't interpolate (returns f0) + assertEquals(3.0, Mathematics.linearInterpolation(3.0, 2.0, 2.0, 3.0, 3.0), 0.0); + } + + @Test + public void testVvSub() throws Exception { + double[] v1 = {5.0, 6.0, 7.0}, v2 = {3.0, 4.0, 5.0}; + + assertArrayEquals(new double[]{2.0, 2.0, 2.0}, Mathematics.vvSub(v1, v2), 0.0); + } } \ No newline at end of file From 9d0b14becbcd26ef991f80a7b15f6a4ab8729e13 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Fri, 11 Dec 2015 16:55:09 +0100 Subject: [PATCH 4/9] Mathematics tests refs #53 --- .../java/eva2/tools/math/Mathematics.java | 21 ++++---- .../java/eva2/tools/math/MathematicsTest.java | 50 +++++++++++++++++++ 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/main/java/eva2/tools/math/Mathematics.java b/src/main/java/eva2/tools/math/Mathematics.java index 94491398..efbccfbd 100644 --- a/src/main/java/eva2/tools/math/Mathematics.java +++ b/src/main/java/eva2/tools/math/Mathematics.java @@ -811,7 +811,7 @@ public final class Mathematics { } /** - * Project the values in x to the range given. The range must be an vector + * Project the values in x to the range given. The range must be a vector * of 2d-arrays each of which containing lower and upper bound in the i-th * dimension. x must not be longer than the available ranges. Values * exceeding the bounds are set on the bound. The number of bound violations @@ -841,9 +841,9 @@ public final class Mathematics { /** * Project the value to the range given. * - * @param v - * @param min - * @param max + * @param v Value + * @param min Lower bound + * @param max Upper bound * @return the closest value to v within [min,max] */ public static double projectValue(double v, double min, double max) { @@ -987,8 +987,8 @@ public final class Mathematics { /** * Rotate the vector by angle alpha around axis i/j * - * @param vect - * @param alpha + * @param vect Vector + * @param alpha Rotation angle * @param i * @param j */ @@ -1003,8 +1003,8 @@ public final class Mathematics { * Rotate a given double vector using a rotation matrix. If the matrix is * null, x will be returned unchanged. Matrix dimensions must fit. * - * @param x - * @param rotMatrix + * @param x Vector + * @param rotMatrix Rotation matrix * @return the rotated vector */ public static double[] rotate(double[] x, Matrix rotMatrix) { @@ -1077,6 +1077,7 @@ public final class Mathematics { * Shift bounds by a constant value in every dimension. * * @param range + * @param dist * @return */ public static void shiftRange(double[][] range, double dist) { @@ -1292,8 +1293,8 @@ public final class Mathematics { /** * Add vectors returning a new vector c = a + b; * - * @param a - * @param b + * @param a Vector 1 + * @param b Vector 2 * @return a new vector c = a + b */ public static double[] vvAdd(double[] a, double[] b) { diff --git a/src/test/java/eva2/tools/math/MathematicsTest.java b/src/test/java/eva2/tools/math/MathematicsTest.java index 20c704d2..29471166 100644 --- a/src/test/java/eva2/tools/math/MathematicsTest.java +++ b/src/test/java/eva2/tools/math/MathematicsTest.java @@ -116,7 +116,29 @@ public class MathematicsTest { @Test public void testProjectToRange() throws Exception { + double[] v = {1.0, 11.0, 7.5, 9.0}; + double[][] range = { + {5.0, 10.0}, + {5.0, 10.0}, + {5.0, 10.0}, + {5.0, 10.0} + }; + int violations = Mathematics.projectToRange(v, range); + + // Has two violations + assertEquals(2, violations); + assertArrayEquals(new double[]{5.0, 10.0, 7.5, 9.0}, v, 0.0); + } + + @Test + public void testProjectToValue() throws Exception { + // Lower range + assertEquals(5.0, Mathematics.projectValue(2.0, 5.0, 10.0), 0.0); + // Upper range + assertEquals(10.0, Mathematics.projectValue(12.0, 5.0, 10.0), 0.0); + // In range + assertEquals(7.5, Mathematics.projectValue(7.5, 5.0, 10.0), 0.0); } @Test @@ -226,4 +248,32 @@ public class MathematicsTest { assertArrayEquals(new double[]{2.0, 2.0, 2.0}, Mathematics.vvSub(v1, v2), 0.0); } + + @Test + public void testVvAdd() throws Exception { + double[] v1 = {5.0, 6.0, 7.0}, v2 = {3.0, 4.0, 5.0}; + + assertArrayEquals(new double[]{8.0, 10.0, 12.0}, Mathematics.vvAdd(v1, v2), 0.0); + } + + @Test + public void testSvMult() throws Exception { + double[] v1 = {3.0, 4.0, 5.0}; + + assertArrayEquals(new double[]{6.0, 8.0, 10.0}, Mathematics.svMult(2.0, v1), 0.0); + } + + @Test + public void testSvDiv() throws Exception { + double[] v1 = {6.0, 8.0, 10.0}; + + assertArrayEquals(new double[]{3.0, 4.0, 5.0}, Mathematics.svDiv(2.0, v1), 0.0); + } + + @Test + public void testSvAdd() throws Exception { + double[] v1 = {3.0, 4.0, 5.0}; + + assertArrayEquals(new double[]{5.0, 6.0, 7.0}, Mathematics.svAdd(2.0, v1), 0.0); + } } \ No newline at end of file From ada94fcb0a7e96ec6c3b1107459d6df50c1728e3 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Fri, 11 Dec 2015 18:58:16 +0100 Subject: [PATCH 5/9] Simple test for ESIndividualDoubleData refs #53 --- .../individuals/ESIndividualDoubleData.java | 16 ++--- .../ESIndividualDoubleDataTest.java | 60 +++++++++++++++++++ 2 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 src/test/java/eva2/optimization/individuals/ESIndividualDoubleDataTest.java diff --git a/src/main/java/eva2/optimization/individuals/ESIndividualDoubleData.java b/src/main/java/eva2/optimization/individuals/ESIndividualDoubleData.java index 04492384..cec0dbf7 100644 --- a/src/main/java/eva2/optimization/individuals/ESIndividualDoubleData.java +++ b/src/main/java/eva2/optimization/individuals/ESIndividualDoubleData.java @@ -13,12 +13,15 @@ import eva2.tools.math.RNG; import eva2.util.annotation.Description; import eva2.util.annotation.Hidden; +import java.util.logging.Logger; + /** * This individual uses a real-valued genotype to code for double values. */ @Description(value = "This is an ES individual suited to optimize double values.") public class ESIndividualDoubleData extends AbstractEAIndividual implements InterfaceESIndividual, InterfaceDataTypeDouble, java.io.Serializable { + private static final Logger LOGGER = Logger.getLogger(ESIndividualDoubleData.class.getName()); private double[] genotype; private double[] phenotype; private double[][] range; @@ -46,7 +49,7 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte this.genotype[i] = individual.genotype[i]; this.range[i][0] = individual.range[i][0]; this.range[i][1] = individual.range[i][1]; - } + }; // cloning the members of AbstractEAIndividual this.age = individual.age; @@ -108,7 +111,7 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte /** * This method allows you to request a certain amount of double data * - * @param length The lenght of the double[] that is to be optimized + * @param length The length of the double[] that is to be optimized */ @Override public void setDoubleDataLength(int length) { @@ -154,7 +157,7 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte @Hidden public void setDoubleRange(double[][] range) { if (range.length != this.range.length) { - System.out.println("Warning: Trying to set a range of length " + range.length + " to a vector of length " + LOGGER.warning("Trying to set a range of length " + range.length + " to a vector of length " + this.range.length + "!\n Use method setDoubleDataLength first! (ESIndividualDoubleData:setDoubleRange)"); } for (int i = 0; ((i < this.range.length) && (i < range.length)); i++) { @@ -209,7 +212,7 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte /** * This method allows you to set the phenotype double data. To change the genotype, - * use SetDoubleDataLamarckian(). + * use #setDoubleDataLamarckian(). * * @param doubleData The new double data. */ @@ -226,7 +229,6 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte */ @Override public void setDoubleGenotype(double[] doubleData) { -// this.setDoublePhenotype(doubleData); this.setDoublePhenotype(null); // tag it as invalid this.genotype = new double[doubleData.length]; System.arraycopy(doubleData, 0, this.genotype, 0, doubleData.length); @@ -271,7 +273,7 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte /** * This method will return a string description of the GAIndividal - * noteably the Genotype. + * notably the Genotype. * * @return A descriptive string */ @@ -390,7 +392,7 @@ public class ESIndividualDoubleData extends AbstractEAIndividual implements Inte } /** - * This method allows the CommonJavaObjectEditorPanel to read the + * This method allows the ObjectEditorPanel to read the * name to the current object. * * @return The name. diff --git a/src/test/java/eva2/optimization/individuals/ESIndividualDoubleDataTest.java b/src/test/java/eva2/optimization/individuals/ESIndividualDoubleDataTest.java new file mode 100644 index 00000000..eefe2944 --- /dev/null +++ b/src/test/java/eva2/optimization/individuals/ESIndividualDoubleDataTest.java @@ -0,0 +1,60 @@ +package eva2.optimization.individuals; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ESIndividualDoubleDataTest { + ESIndividualDoubleData indy; + + @Before + public void setUp() throws Exception { + indy = new ESIndividualDoubleData(); + } + + @Test + public void testEqualGenotypes() throws Exception { + // Genotype of two different types is not equal + assertFalse(indy.equalGenotypes(new ESIndividualBinaryData())); + + // Default init genotype should be equal + assertTrue(indy.equalGenotypes(new ESIndividualDoubleData())); + } + + @Test + public void testSize() throws Exception { + // Default individual has size 1 + assertEquals(1, indy.size()); + + // Returns length of genotype + indy.setDoubleGenotype(new double[]{1.0, 1.0, 1.0, 1.0, 1.0}); + assertEquals(5, indy.size()); + } + + @Test + public void testSetDoubleGenotype() throws Exception { + double[] genotype = {1.0, 1.0, 1.0, 1.0, 1.0}; + + indy.setDoubleGenotype(genotype); + + // Setting the genotype clears the phenotype and matches the genotype + assertArrayEquals(genotype, indy.getDoubleData(), 0.0); + + assertArrayEquals(genotype, indy.getDGenotype(), 0.0); + } + + @Test + public void testGetStringRepresentation() throws Exception { + assertEquals( + "ESIndividual coding double: (Fitness {0.0;}/SelProb{0.0;}) Value: [0.0; ]", + indy.getStringRepresentation() + ); + } + + @Test + public void testEqual() throws Exception { + // Is equal to itself + assertTrue(indy.equals(indy)); + } +} \ No newline at end of file From f58f6e867baac885c5dec7bdd7a619c4eaa29ea2 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Fri, 11 Dec 2015 19:23:45 +0100 Subject: [PATCH 6/9] Some basic tests for Population refs #53 --- .../optimization/population/Population.java | 8 +- .../population/PopulationTest.java | 356 ++++++++++++++++++ 2 files changed, 360 insertions(+), 4 deletions(-) create mode 100644 src/test/java/eva2/optimization/population/PopulationTest.java diff --git a/src/main/java/eva2/optimization/population/Population.java b/src/main/java/eva2/optimization/population/Population.java index 9ae123a2..90f8b9a4 100644 --- a/src/main/java/eva2/optimization/population/Population.java +++ b/src/main/java/eva2/optimization/population/Population.java @@ -163,7 +163,6 @@ public class Population extends ArrayList implements Popul } Population sols = allSolutions.getSolutions(); for (int i = 0; i < sols.size(); i++) { -// addPopulation(allSolutions.getSolutions()); if (!checkCols.containsKey(sols.getEAIndividual(i).getIndyID())) { add(sols.getEAIndividual(i)); } @@ -1850,7 +1849,8 @@ public class Population extends ArrayList implements Popul /** * Returns the average, minimal and maximal individual distance as diversity * measure for the population. If the given metric argument is null, the - * euclidian distance of individual positions is used, which presumes that {@link eva2.optimization.individuals.AbstractEAIndividual#getDoublePosition(eva2.optimization.individuals.AbstractEAIndividual)} + * euclidean distance of individual positions is used, which presumes that + * {@link AbstractEAIndividual#getDoublePosition(AbstractEAIndividual)} * returns a valid double position for the individuals of the population. * This is of course rather expensive computationally. * @@ -1858,7 +1858,6 @@ public class Population extends ArrayList implements Popul * an array of three */ public double[] getPopulationMeasures(InterfaceDistanceMetric metric) { - double[] res = getPopulationMeasures(this, metric); return res; } @@ -1866,7 +1865,8 @@ public class Population extends ArrayList implements Popul /** * Returns the average, minimal and maximal individual distance as diversity * measure for the population. If the given metric argument is null, the - * euclidian distance of individual positions is used, which presumes that {@link AbstractEAIndividual#getDoublePosition(eva2.optimization.individuals.AbstractEAIndividual)} + * euclidean distance of individual positions is used, which presumes that + * {@link AbstractEAIndividual#getDoublePosition(AbstractEAIndividual)} * returns a valid double position for the individuals of the population. * This is of course rather expensive computationally. * diff --git a/src/test/java/eva2/optimization/population/PopulationTest.java b/src/test/java/eva2/optimization/population/PopulationTest.java new file mode 100644 index 00000000..488859d2 --- /dev/null +++ b/src/test/java/eva2/optimization/population/PopulationTest.java @@ -0,0 +1,356 @@ +package eva2.optimization.population; + +import eva2.optimization.individuals.ESIndividualDoubleData; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +public class PopulationTest { + Population emptyPopulation; + + @Before + public void setUp() throws Exception { + emptyPopulation = new Population(10); + } + + @Test + public void testEquals() throws Exception { + + } + + @Test + public void testPutData() throws Exception { + + } + + @Test + public void testGetData() throws Exception { + + } + + @Test + public void testHasData() throws Exception { + + } + + @Test + public void testResetProperties() throws Exception { + + } + + @Test + public void testGetInitPos() throws Exception { + + } + + @Test + public void testSetInitPos() throws Exception { + + } + + @Test + public void testSetInitAround() throws Exception { + + } + + @Test + public void testGetInitAround() throws Exception { + + } + + @Test + public void testFill() throws Exception { + assertEquals(0, emptyPopulation.size()); + + emptyPopulation.fill(new ESIndividualDoubleData()); + + // Should be filled with 10 individuals + assertEquals(10, emptyPopulation.getTargetSize()); + } + + @Test + public void testSetUseHistory() throws Exception { + + } + + @Test + public void testIsUsingHistory() throws Exception { + + } + + @Test + public void testSetAutoAging() throws Exception { + + } + + @Test + public void testIsAutoAging() throws Exception { + + } + + @Test + public void testSetMaxHistoryLength() throws Exception { + + } + + @Test + public void testGetMaxHistLength() throws Exception { + + } + + @Test + public void testGetHistoryLength() throws Exception { + + } + + @Test + public void testGetHistory() throws Exception { + + } + + @Test + public void testSetHistory() throws Exception { + + } + + @Test + public void testIncrFunctionCalls() throws Exception { + int currentFunctionCalls = emptyPopulation.getFunctionCalls(); + emptyPopulation.incrFunctionCalls(); + assertEquals(currentFunctionCalls + 1, emptyPopulation.getFunctionCalls()); + } + + @Test + public void testIncrFunctionCallsBy() throws Exception { + int currentFunctionCalls = emptyPopulation.getFunctionCalls(); + emptyPopulation.incrFunctionCallsBy(150); + assertEquals(currentFunctionCalls + 150, emptyPopulation.getFunctionCalls()); + } + + @Test + public void testGetFunctionCalls() throws Exception { + // New and empty population has 0 function calls + assertEquals(0, this.emptyPopulation.getFunctionCalls()); + } + + @Test + public void testSetFunctionCalls() throws Exception { + emptyPopulation.setFunctionCalls(150); + assertEquals(150, emptyPopulation.getFunctionCalls()); + } + + @Test + public void testSetAllFitnessValues() throws Exception { + + } + + @Test + public void testIncrGeneration() throws Exception { + int currentGeneration = emptyPopulation.getGeneration(); + emptyPopulation.incrGeneration(); + + assertEquals(currentGeneration + 1, emptyPopulation.getGeneration()); + } + + @Test + public void testGetGeneration() throws Exception { + // New population has generation 0 + assertEquals(0, emptyPopulation.getGeneration()); + } + + @Test + public void testSetGeneration() throws Exception { + emptyPopulation.setGeneration(10); + assertEquals(10, emptyPopulation.getGeneration()); + } + + @Test + public void testAddPopulation() throws Exception { + + } + + @Test + public void testAddPopulation1() throws Exception { + + } + + @Test + public void testResetFitness() throws Exception { + + } + + @Test + public void testGetDominatingSet() throws Exception { + + } + + @Test + public void testGetDominatingSet1() throws Exception { + + } + + @Test + public void testGetIndexOfBestIndividualPrefFeasible() throws Exception { + + } + + @Test + public void testGetIndexOfWorstIndividualNoConstr() throws Exception { + + } + + @Test + public void testGetIndexOfBestIndividualPrefFeasible1() throws Exception { + + } + + @Test + public void testGetIndexOfWorstIndividualNoConstr1() throws Exception { + + } + + @Test + public void testMoveNInds() throws Exception { + + } + + @Test + public void testMoveRandIndFromTo() throws Exception { + + } + + @Test + public void testGetSpecificData() throws Exception { + + } + + @Test + public void testGetSpecificDataNames() throws Exception { + + } + + @Test + public void testGetIDList() throws Exception { + + } + + @Test + public void testGetIndyList() throws Exception { + + } + + @Test + public void testSetTargetSize() throws Exception { + + } + + @Test + public void testSetTargetPopSize() throws Exception { + + } + + @Test + public void testGetBestIndividual() throws Exception { + + } + + @Test + public void testGetWorstIndividual() throws Exception { + + } + + @Test + public void testGetBestFitness() throws Exception { + + } + + @Test + public void testGetWorstFitness() throws Exception { + + } + + @Test + public void testGetMeanFitness() throws Exception { + + } + + @Test + public void testGetPopulationMeasures() throws Exception { + + } + + @Test + public void testGetCorrelations() throws Exception { + + } + + @Test + public void testGetCorrelations1() throws Exception { + + } + + @Test + public void testGetFitnessMeasures() throws Exception { + + } + + @Test + public void testGetCenter() throws Exception { + + } + + @Test + public void testGetCenterIndy() throws Exception { + + } + + @Test + public void testGetCenterWeighted() throws Exception { + + } + + @Test + public void testGetNeighborIndex() throws Exception { + + } + + @Test + public void testGetFitSum() throws Exception { + + } + + @Test + public void testUpdateRange() throws Exception { + + } + + @Test + public void testTargetSizeReached() throws Exception { + + } + + @Test + public void testTargetSizeExceeded() throws Exception { + + } + + @Test + public void testGetFreeSlots() throws Exception { + + } + + @Test + public void testClearHistory() throws Exception { + + } + + @Test + public void testCheckNoNullIndy() throws Exception { + + } + + @Test + public void testFilterByFitness() throws Exception { + + } +} \ No newline at end of file From fbb1c80d09d028ce18fa1786bb6bd63993ddd7df Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Sat, 12 Dec 2015 12:58:45 +0100 Subject: [PATCH 7/9] More Population testing refs #53 --- .../operator/cluster/ClusteringKMeans.java | 17 ++------ .../optimization/population/Population.java | 2 +- src/main/java/eva2/tools/ToolBox.java | 2 +- .../population/PopulationTest.java | 39 ++++++++++++++++++- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/main/java/eva2/optimization/operator/cluster/ClusteringKMeans.java b/src/main/java/eva2/optimization/operator/cluster/ClusteringKMeans.java index 7a4cf3fa..5500e629 100644 --- a/src/main/java/eva2/optimization/operator/cluster/ClusteringKMeans.java +++ b/src/main/java/eva2/optimization/operator/cluster/ClusteringKMeans.java @@ -305,8 +305,8 @@ public class ClusteringKMeans implements InterfaceClustering, java.io.Serializab /** * This method calculates the distance between two double values * - * @param d1 - * @param d2 + * @param indy + * @param p * @return The scalar distances between d1 and d2 */ private double distance(AbstractEAIndividual indy, double[] p) { @@ -357,19 +357,8 @@ public class ClusteringKMeans implements InterfaceClustering, java.io.Serializab return metric.distance(species1.getBestEAIndividual(), species2.getBestEAIndividual()) < mergeDist; } -// /** This method decides if a unclustered individual belongs to an already established species. -// * @param indy A unclustered individual. -// * @param species A species. -// * @return True or False. -// */ -// public boolean belongsToSpecies(AbstractEAIndividual indy, Population species, Population pop) { -// // @todo perhaps the same as in convergingSpecies -// return false; -// } - @Override public int[] associateLoners(Population loners, Population[] species, Population referencePop) { -// tmpIndy = (AbstractEAIndividual)loners.getEAIndividual(0).clone(); int[] res = new int[loners.size()]; System.err.println("Warning, associateLoners not implemented for " + this.getClass()); Arrays.fill(res, -1); @@ -413,7 +402,7 @@ public class ClusteringKMeans implements InterfaceClustering, java.io.Serializab /** * This method allows you to set/get the number of - * clusters tofind + * clusters to find * * @return The current number of clusters to find. */ diff --git a/src/main/java/eva2/optimization/population/Population.java b/src/main/java/eva2/optimization/population/Population.java index 90f8b9a4..18cbaab9 100644 --- a/src/main/java/eva2/optimization/population/Population.java +++ b/src/main/java/eva2/optimization/population/Population.java @@ -375,7 +375,7 @@ public class Population extends ArrayList implements Popul this.historyList = new LinkedList<>(); this.generationCount = 0; this.functionCallCount = 0; - double[] popSeed = null; + double[] popSeed; if (this.populationArchive != null) { this.populationArchive.clear(); this.populationArchive.initialize(); diff --git a/src/main/java/eva2/tools/ToolBox.java b/src/main/java/eva2/tools/ToolBox.java index 9ac24240..c4c5b8b6 100644 --- a/src/main/java/eva2/tools/ToolBox.java +++ b/src/main/java/eva2/tools/ToolBox.java @@ -31,7 +31,7 @@ public final class ToolBox { ret[i] = fields[i].toString(); } - System.arraycopy(additionalValues, enumLen - enumLen, ret, enumLen, ret.length - enumLen); + System.arraycopy(additionalValues, 0, ret, enumLen, ret.length - enumLen); return ret; } diff --git a/src/test/java/eva2/optimization/population/PopulationTest.java b/src/test/java/eva2/optimization/population/PopulationTest.java index 488859d2..9b74d848 100644 --- a/src/test/java/eva2/optimization/population/PopulationTest.java +++ b/src/test/java/eva2/optimization/population/PopulationTest.java @@ -25,12 +25,36 @@ public class PopulationTest { @Test public void testGetData() throws Exception { + // Simple data + emptyPopulation.putData("someInt", 12); + assertEquals(12, emptyPopulation.getData("someInt")); + // Arrays + double[] doubleArray = new double[]{1.0}; + emptyPopulation.putData("someDoubleArray", doubleArray); + assertArrayEquals(doubleArray, (double[])emptyPopulation.getData("someDoubleArray"), 0.0); + + // Objects + Object obj = new Object(); + emptyPopulation.putData("someObject", obj); + assertEquals(obj, emptyPopulation.getData("someObject")); } @Test public void testHasData() throws Exception { + assertFalse(emptyPopulation.hasData("someKey")); + // Simple data + emptyPopulation.putData("someInt", 12); + assertTrue(emptyPopulation.hasData("someInt")); + + // Arrays + emptyPopulation.putData("someDoubleArray", new double[]{1.0}); + assertTrue(emptyPopulation.hasData("someDoubleArray")); + + // Objects + emptyPopulation.putData("someObject", new Object()); + assertTrue(emptyPopulation.hasData("someObject")); } @Test @@ -70,22 +94,33 @@ public class PopulationTest { @Test public void testSetUseHistory() throws Exception { + emptyPopulation.setUseHistory(true); + assertTrue(emptyPopulation.isUsingHistory()); + emptyPopulation.setUseHistory(false); + assertFalse(emptyPopulation.isUsingHistory()); } @Test public void testIsUsingHistory() throws Exception { - + // Not using history by default + assertFalse(emptyPopulation.isUsingHistory()); } @Test public void testSetAutoAging() throws Exception { + emptyPopulation.setAutoAging(true); + assertTrue(emptyPopulation.isAutoAging()); + + emptyPopulation.setAutoAging(false); + assertFalse(emptyPopulation.isAutoAging()); } @Test public void testIsAutoAging() throws Exception { - + // Is auto-aging by default + assertTrue(emptyPopulation.isAutoAging()); } @Test From 0002b5a7979a5468c815752e3a5f9bdbe3efeff4 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Sat, 12 Dec 2015 17:46:28 +0100 Subject: [PATCH 8/9] Another Population test refs #53 --- .../individuals/AbstractEAIndividual.java | 2 +- .../optimization/population/PopulationTest.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/eva2/optimization/individuals/AbstractEAIndividual.java b/src/main/java/eva2/optimization/individuals/AbstractEAIndividual.java index e1f3e3c1..37a8562d 100644 --- a/src/main/java/eva2/optimization/individuals/AbstractEAIndividual.java +++ b/src/main/java/eva2/optimization/individuals/AbstractEAIndividual.java @@ -1088,7 +1088,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java. } return pos; } // TODO check some more types here? - EVAERROR.errorMsgOnce("Unhandled case in AbstractEAIndividual.getPosition()!"); + EVAERROR.errorMsgOnce("Unhandled case in AbstractEAIndividual.getDoublePositionShallow()!"); return null; } diff --git a/src/test/java/eva2/optimization/population/PopulationTest.java b/src/test/java/eva2/optimization/population/PopulationTest.java index 9b74d848..ad978339 100644 --- a/src/test/java/eva2/optimization/population/PopulationTest.java +++ b/src/test/java/eva2/optimization/population/PopulationTest.java @@ -386,6 +386,19 @@ public class PopulationTest { @Test public void testFilterByFitness() throws Exception { + ESIndividualDoubleData indy1, indy2, indy3; + indy1 = new ESIndividualDoubleData(); + indy1.setFitness(new double[]{100.0}); + indy2 = new ESIndividualDoubleData(); + indy2.setFitness(new double[]{10.0}); + indy3 = new ESIndividualDoubleData(); + indy3.setFitness(new double[]{1.0}); + emptyPopulation.add(indy1); + emptyPopulation.add(indy2); + emptyPopulation.add(indy2); + + // Get all individuals with fitness <= 10.0 (first fitness dimension) + assertEquals(2, emptyPopulation.filterByFitness(10.0, 0).size()); } } \ No newline at end of file From 07066578d5af5bdaf014a42751c302de22984ead Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Mon, 14 Dec 2015 15:46:54 +0100 Subject: [PATCH 9/9] Test Mnemonic, simplify class refs #53 --- src/main/java/eva2/gui/Mnemonic.java | 16 ++++----- src/test/java/eva2/gui/MnemonicTest.java | 44 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 src/test/java/eva2/gui/MnemonicTest.java diff --git a/src/main/java/eva2/gui/Mnemonic.java b/src/main/java/eva2/gui/Mnemonic.java index 0833bc59..e2c2b94b 100644 --- a/src/main/java/eva2/gui/Mnemonic.java +++ b/src/main/java/eva2/gui/Mnemonic.java @@ -5,30 +5,26 @@ package eva2.gui; */ class Mnemonic { - private char mnemonic; - private String text; + private final char mnemonic; + private final String text; /** * */ public Mnemonic(String s) { - setString(s); - } - - /** - * - */ - public void setString(String s) { StringBuilder buf = new StringBuilder(s); + char c = Character.MIN_VALUE; + for (int i = 0; i < buf.length(); i++) { if (buf.charAt(i) == '&') { buf.deleteCharAt(i); i++; if (i < buf.length() && buf.charAt(i) != '&') { - mnemonic = buf.charAt(i - 1); + c = buf.charAt(i - 1); } } } + mnemonic = c; text = buf.toString(); } diff --git a/src/test/java/eva2/gui/MnemonicTest.java b/src/test/java/eva2/gui/MnemonicTest.java new file mode 100644 index 00000000..bcaeebc3 --- /dev/null +++ b/src/test/java/eva2/gui/MnemonicTest.java @@ -0,0 +1,44 @@ +package eva2.gui; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MnemonicTest { + + @Test + public void testMnemonic() throws Exception { + Mnemonic m = new Mnemonic("No mnemonic"); + + // String without ampersand does not have a mnemonic + assertEquals(0, m.getMnemonic()); + + // Detects ampersand at beginning + m = new Mnemonic("&Fancy"); + assertEquals('F', m.getMnemonic()); + + // Detects ampersand in the middle + m = new Mnemonic("Super&fancy"); + assertEquals('f', m.getMnemonic()); + + // Handles ampersand at the end + m = new Mnemonic("Hellyea&"); + assertEquals(0, m.getMnemonic()); + } + + @Test + public void testGetMnemonic() throws Exception { + Mnemonic m = new Mnemonic("Super &great"); + assertEquals('g', m.getMnemonic()); + } + + @Test + public void testGetText() throws Exception { + Mnemonic m1 = new Mnemonic("The text"); + assertEquals("The text", m1.getText()); + + Mnemonic m2 = new Mnemonic("&Mnemonic"); + assertEquals("Mnemonic", m2.getText()); + + } +} \ No newline at end of file