diff --git a/opt4j-core/src/main/java/org/opt4j/core/genotype/BooleanMapGenotype.java b/opt4j-core/src/main/java/org/opt4j/core/genotype/BooleanMapGenotype.java index f860a4be..6c125ab2 100644 --- a/opt4j-core/src/main/java/org/opt4j/core/genotype/BooleanMapGenotype.java +++ b/opt4j-core/src/main/java/org/opt4j/core/genotype/BooleanMapGenotype.java @@ -19,14 +19,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *******************************************************************************/ - + package org.opt4j.core.genotype; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Random; +import java.util.Set; import org.opt4j.core.Genotype; @@ -42,8 +44,8 @@ * Example usage:
* *
- * BooleanMapGenotype<Switch> genotype = new BooleanMapGenotype<Switch>(Arrays.asList(switch1, switch2, switch3, switch4,
- * 		switch5));
+ * BooleanMapGenotype<Switch> genotype = new BooleanMapGenotype<Switch>(
+ * 		Arrays.asList(switch1, switch2, switch3, switch4, switch5));
  * genotype.init(new Random());
  * 
* @@ -69,6 +71,10 @@ public class BooleanMapGenotype extends BooleanGenotype implements MapGenotyp */ public BooleanMapGenotype(List list) { super(); + Set uniqueKeys = new HashSet(list); + if (uniqueKeys.size() < list.size()) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_NON_UNIQUE_KEYS); + } this.list = list; } @@ -89,7 +95,7 @@ public void init(Random random) { */ @Override public void init(Random random, int n) { - throw new UnsupportedOperationException("Use method init(Random) instead"); + throw new UnsupportedOperationException(MapGenotype.ERROR_MESSAGE_UNSUPPORTED_INIT); } /* @@ -99,6 +105,9 @@ public void init(Random random, int n) { */ @Override public Boolean getValue(K key) { + if (!containsKey(key)) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_INVALID_KEY); + } int i = list.indexOf(key); return get(i); } @@ -111,6 +120,9 @@ public Boolean getValue(K key) { */ @Override public void setValue(K key, Boolean value) { + if (!containsKey(key)) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_INVALID_KEY); + } int i = list.indexOf(key); while (size() <= i) { add(false); @@ -151,13 +163,15 @@ public G newInstance() { */ @Override public String toString() { - String s = "["; + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("["); for (int i = 0; i < size(); i++) { K key = list.get(i); boolean value = this.get(i); - s += key + "=" + value + ";"; + stringBuilder.append(key + "=" + value + ";"); } - return s + "]"; + stringBuilder.append("]"); + return stringBuilder.toString(); } /* @@ -167,6 +181,9 @@ public String toString() { */ @Override public int getIndexOf(K key) { + if (!containsKey(key)){ + throw new IllegalArgumentException(ERROR_MESSAGE_INVALID_KEY); + } return list.indexOf(key); } diff --git a/opt4j-core/src/main/java/org/opt4j/core/genotype/DoubleMapGenotype.java b/opt4j-core/src/main/java/org/opt4j/core/genotype/DoubleMapGenotype.java index 4191a549..fd3dcd19 100644 --- a/opt4j-core/src/main/java/org/opt4j/core/genotype/DoubleMapGenotype.java +++ b/opt4j-core/src/main/java/org/opt4j/core/genotype/DoubleMapGenotype.java @@ -19,14 +19,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *******************************************************************************/ - + package org.opt4j.core.genotype; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Random; +import java.util.Set; import org.opt4j.core.Genotype; @@ -42,8 +44,8 @@ * Example usage:
* *
- * DoubleMapGenotype<Bottle> genotype = new DoubleMapGenotype<Bottle>(Arrays.asList(bottle1, bottle2, bottle3, bottle4,
- * 		bottle5));
+ * DoubleMapGenotype<Bottle> genotype = new DoubleMapGenotype<Bottle>(
+ * 		Arrays.asList(bottle1, bottle2, bottle3, bottle4, bottle5));
  * genotype.init(new Random());
  * 
* @@ -72,6 +74,10 @@ public class DoubleMapGenotype extends DoubleGenotype implements MapGenotype< */ public DoubleMapGenotype(List keys, Bounds bounds) { super(bounds); + Set uniqueKeys = new HashSet(keys); + if (uniqueKeys.size() < keys.size()) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_NON_UNIQUE_KEYS); + } this.keys = keys; } @@ -93,7 +99,7 @@ public void init(Random random) { */ @Override public void init(Random random, int n) { - throw new UnsupportedOperationException("Use method init(Random) instead"); + throw new UnsupportedOperationException(MapGenotype.ERROR_MESSAGE_UNSUPPORTED_INIT); } /* @@ -125,7 +131,12 @@ public Double getValue(K key) { */ @Override public void setValue(K key, Double value) { + if (!containsKey(key)) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_INVALID_KEY); + } int i = keys.indexOf(key); + if (value < bounds.getLowerBound(i) || value > bounds.getUpperBound(i)) + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_OUT_OF_BOUNDS); while (size() <= i) { add(bounds.getLowerBound(i)); } @@ -155,13 +166,15 @@ public G newInstance() { */ @Override public String toString() { - String s = "["; + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("["); for (int i = 0; i < size(); i++) { K key = keys.get(i); double value = this.get(i); - s += key + "=" + value + ";"; + stringBuilder.append(key + "=" + value + ";"); } - return s + "]"; + stringBuilder.append("]"); + return stringBuilder.toString(); } /* @@ -171,6 +184,9 @@ public String toString() { */ @Override public int getIndexOf(K key) { + if (!containsKey(key)) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_INVALID_KEY); + } return keys.indexOf(key); } diff --git a/opt4j-core/src/main/java/org/opt4j/core/genotype/IntegerMapGenotype.java b/opt4j-core/src/main/java/org/opt4j/core/genotype/IntegerMapGenotype.java index fc199a84..2ac00fdb 100644 --- a/opt4j-core/src/main/java/org/opt4j/core/genotype/IntegerMapGenotype.java +++ b/opt4j-core/src/main/java/org/opt4j/core/genotype/IntegerMapGenotype.java @@ -72,7 +72,7 @@ public IntegerMapGenotype(List list, Bounds bounds) { super(bounds); Set uniqueKeys = new HashSet(list); if (uniqueKeys.size() < list.size()) { - throw new IllegalArgumentException("The provided key objects have to be unique"); + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_NON_UNIQUE_KEYS); } this.list = list; } @@ -89,6 +89,10 @@ public IntegerMapGenotype(List list, Bounds bounds) { */ public IntegerMapGenotype(List list, int lowerBound, int upperBound) { super(lowerBound, upperBound); + Set uniqueKeys = new HashSet(list); + if (uniqueKeys.size() < list.size()) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_NON_UNIQUE_KEYS); + } this.list = list; } @@ -110,7 +114,7 @@ public void init(Random random) { */ @Override public void init(Random random, int n) { - throw new UnsupportedOperationException("Use method init(Random) instead"); + throw new UnsupportedOperationException(MapGenotype.ERROR_MESSAGE_UNSUPPORTED_INIT); } /* @@ -130,6 +134,9 @@ public boolean containsKey(K key) { */ @Override public Integer getValue(K key) { + if (!containsKey(key)) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_INVALID_KEY); + } int i = list.indexOf(key); return get(i); } @@ -142,16 +149,15 @@ public Integer getValue(K key) { */ @Override public void setValue(K key, Integer value) { - if (!list.contains(key)) { - throw new IllegalArgumentException("Invalid key"); + if (!containsKey(key)) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_INVALID_KEY); } int i = list.indexOf(key); while (size() <= i) { add(bounds.getLowerBound(size())); } if (bounds.getLowerBound(i) > value || bounds.getUpperBound(i) < value) { - throw new IllegalArgumentException( - "The provided value does not lie within the bounds for the provided key"); + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_OUT_OF_BOUNDS); } set(i, value); } @@ -183,7 +189,7 @@ public String toString() { stringBuilder.append("["); for (int i = 0; i < size(); i++) { K key = list.get(i); - double value = this.get(i); + int value = this.get(i); stringBuilder.append(key + "=" + value + ";"); } stringBuilder.append("]"); @@ -197,8 +203,8 @@ public String toString() { */ @Override public int getIndexOf(K key) { - if (!list.contains(key)) { - throw new IllegalArgumentException("Invalid key"); + if (!containsKey(key)) { + throw new IllegalArgumentException(MapGenotype.ERROR_MESSAGE_INVALID_KEY); } return list.indexOf(key); } diff --git a/opt4j-core/src/main/java/org/opt4j/core/genotype/MapGenotype.java b/opt4j-core/src/main/java/org/opt4j/core/genotype/MapGenotype.java index 7cb8f8fc..73fcbfce 100644 --- a/opt4j-core/src/main/java/org/opt4j/core/genotype/MapGenotype.java +++ b/opt4j-core/src/main/java/org/opt4j/core/genotype/MapGenotype.java @@ -19,7 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *******************************************************************************/ - package org.opt4j.core.genotype; @@ -39,6 +38,11 @@ */ public interface MapGenotype { + static final String ERROR_MESSAGE_NON_UNIQUE_KEYS = "The provided key objects have to be unique"; + static final String ERROR_MESSAGE_INVALID_KEY = "Invalid key"; + static final String ERROR_MESSAGE_OUT_OF_BOUNDS = "The provided value does not lie within the bounds for the provided key"; + static final String ERROR_MESSAGE_UNSUPPORTED_INIT = "Use method init(Random) instead"; + /** * Return all keys. * @@ -47,7 +51,8 @@ public interface MapGenotype { public Collection getKeys(); /** - * Returns the value for the specified key. + * Returns the value for the specified key. Throws an exception if the key + * is not contained. * * @see #setValue * @param key @@ -57,7 +62,8 @@ public interface MapGenotype { public V getValue(K key); /** - * Sets the value for the specified key. + * Sets the value for the specified key. Throws an exception if the key is + * not contained. * * @see #getValue * @param key @@ -77,7 +83,8 @@ public interface MapGenotype { public boolean containsKey(K key); /** - * Returns the index of the key. + * Returns the index of the key. Throws an exception if the key is not + * contained. * * @param key * the key diff --git a/opt4j-core/src/test/java/org/opt4j/core/genotype/BooleanMapGenotypeTest.java b/opt4j-core/src/test/java/org/opt4j/core/genotype/BooleanMapGenotypeTest.java new file mode 100644 index 00000000..5f7326a6 --- /dev/null +++ b/opt4j-core/src/test/java/org/opt4j/core/genotype/BooleanMapGenotypeTest.java @@ -0,0 +1,87 @@ +package org.opt4j.core.genotype; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; + +import org.junit.Test; + +public class BooleanMapGenotypeTest { + + @SuppressWarnings("serial") + class MockRandom extends Random { + @Override + public boolean nextBoolean() { + return false; + } + } + + @SuppressWarnings("serial") + class MockList extends ArrayList { + public MockList() { + add(1); + add(2); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidKeyGetIndex() { + BooleanMapGenotype geno = new BooleanMapGenotype(new MockList()); + geno.getIndexOf(3); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidKeySetValue() { + BooleanMapGenotype geno = new BooleanMapGenotype(new MockList()); + geno.setValue(3, true); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidKeyGetValue() { + BooleanMapGenotype geno = new BooleanMapGenotype(new MockList()); + geno.getValue(3); + } + + @Test(expected = UnsupportedOperationException.class) + public void testWrongInit() { + BooleanMapGenotype geno = new BooleanMapGenotype(new MockList()); + geno.init(new MockRandom(), 2); + } + + @Test + public void testConstructor() { + BooleanMapGenotype geno = new BooleanMapGenotype(new MockList()); + assertTrue(geno.isEmpty()); + geno.setValue(1, true); + assertEquals(1, geno.size()); + geno.init(new MockRandom()); + assertEquals(2, geno.size()); + assertFalse(geno.getValue(1)); + geno.setValue(1, true); + assertTrue(geno.getValue(1)); + assertTrue(geno.containsKey(1)); + assertFalse(geno.containsKey(3)); + assertEquals(0, geno.getIndexOf(1)); + Set keys = new HashSet(geno.getKeys()); + assertEquals(2, keys.size()); + assertTrue(keys.contains(1)); + assertTrue(keys.contains(2)); + BooleanMapGenotype other = geno.newInstance(); + assertNotEquals(geno, other); + assertTrue(other.isEmpty()); + assertEquals("[1=true;2=false;]", geno.toString()); + } + + @Test(expected = IllegalArgumentException.class) + public void testNonUniqueKeys() { + List keyList = new ArrayList(); + keyList.add(1); + keyList.add(1); + new BooleanMapGenotype(keyList); + } + +} diff --git a/opt4j-core/src/test/java/org/opt4j/core/genotype/DoubleMapGenotypeTest.java b/opt4j-core/src/test/java/org/opt4j/core/genotype/DoubleMapGenotypeTest.java new file mode 100644 index 00000000..34807a5e --- /dev/null +++ b/opt4j-core/src/test/java/org/opt4j/core/genotype/DoubleMapGenotypeTest.java @@ -0,0 +1,226 @@ +package org.opt4j.core.genotype; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Random; + +import org.junit.Test; + +public class DoubleMapGenotypeTest { + + private static double[] lower = { 1.0, 1.0 }; + private static double[] lower2 = { -1.0, -1.0 }; + private static double[] upper = { 1.0, 1.0 }; + + class MockBounds extends DoubleBounds { + + public MockBounds() { + super(DoubleMapGenotypeTest.lower, DoubleMapGenotypeTest.upper); + } + + } + + class MockObject { + protected final int field; + + public MockObject(int field) { + this.field = field; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + getOuterType().hashCode(); + result = prime * result + field; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MockObject other = (MockObject) obj; + if (!getOuterType().equals(other.getOuterType())) + return false; + if (field != other.field) + return false; + return true; + } + + @Override + public String toString() { + return "m" + field; + } + + private DoubleMapGenotypeTest getOuterType() { + return DoubleMapGenotypeTest.this; + } + } + + @Test(expected=UnsupportedOperationException.class) + public void testWrongInitCall(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + keys.add(m1); + keys.add(m2); + DoubleBounds bounds = new DoubleBounds(lower2, upper); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + bounds); + doubleMapGeno.init(new Random(), 10); + } + + @Test + public void testSetValue(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + keys.add(m1); + keys.add(m2); + DoubleBounds bounds = new DoubleBounds(lower2, upper); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + bounds); + doubleMapGeno.setValue(m2, 0.4); + assertEquals(0.4, doubleMapGeno.getValue(m2), 0.0); + doubleMapGeno.init(new Random()); + doubleMapGeno.setValue(m1, 0.5); + assertEquals(0.5, doubleMapGeno.getValue(m1), 0.0); + } + + @Test(expected=IllegalArgumentException.class) + public void testSetValueOutOfBounds2(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + doubleMapGeno.setValue(m1, -2.0); + } + + @Test(expected=IllegalArgumentException.class) + public void testSetValueOutOfBounds1(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + doubleMapGeno.setValue(m1, 2.0); + } + + @Test(expected=IllegalArgumentException.class) + public void testSetValueInvalidKey(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + MockObject m3 = new MockObject(3); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + doubleMapGeno.setValue(m3, 1.0); + } + + @Test + public void testNewInstance(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + doubleMapGeno.init(new Random()); + DoubleMapGenotype other = doubleMapGeno.newInstance(); + assertNotEquals(doubleMapGeno, other); + assertTrue(other.isEmpty()); + } + + @Test + public void testToString(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + doubleMapGeno.init(new Random()); + assertEquals("[m1=1.0;m2=1.0;]", doubleMapGeno.toString()); + } + + @Test + public void testGetIndexOf(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + assertEquals(0, doubleMapGeno.getIndexOf(m1)); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetIndexOfInvalidKey(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + MockObject m3 = new MockObject(3); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + doubleMapGeno.getIndexOf(m3); + } + + @Test + public void testGetKeys(){ + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + Collection ks = doubleMapGeno.getKeys(); + assertEquals(2, ks.size()); + assertTrue(ks.contains(m1)); + assertTrue(ks.contains(m2)); + } + + @Test() + public void testContainsKey() { + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + MockObject m2 = new MockObject(2); + MockObject m3 = new MockObject(3); + keys.add(m1); + keys.add(m2); + DoubleMapGenotype doubleMapGeno = new DoubleMapGenotype(keys, + new MockBounds()); + assertTrue(doubleMapGeno.containsKey(m1)); + assertFalse(doubleMapGeno.containsKey(m3)); + } + + @Test(expected = IllegalArgumentException.class) + public void testNonUniqueKeys() { + List keys = new ArrayList(); + MockObject m1 = new MockObject(1); + keys.add(m1); + keys.add(m1); + new DoubleMapGenotype(keys, new MockBounds()); + } + +} diff --git a/opt4j-core/src/test/java/org/opt4j/core/genotype/IntegerMapGenotypeTest.java b/opt4j-core/src/test/java/org/opt4j/core/genotype/IntegerMapGenotypeTest.java index 25e36740..e12d861e 100644 --- a/opt4j-core/src/test/java/org/opt4j/core/genotype/IntegerMapGenotypeTest.java +++ b/opt4j-core/src/test/java/org/opt4j/core/genotype/IntegerMapGenotypeTest.java @@ -102,6 +102,29 @@ public void testNonUniqueKeys() { new IntegerMapGenotype(inputList, bounds); } + @Test(expected = IllegalArgumentException.class) + public void testGetValueMissingKey() { + int lower = 1; + int upper = 2; + MockObject m1 = new MockObject(1.0, 1); + List list = new ArrayList(); + list.add(m1); + IntegerMapGenotype geno = new IntegerMapGenotype(list, lower, + upper); + geno.getValue(new MockObject(1.0, 2)); + } + + @Test(expected = IllegalArgumentException.class) + public void testNonUniqueKeysBoundConstructor() { + int lower = 1; + int upper = 2; + MockObject m1 = new MockObject(1.0, 1); + List list = new ArrayList(); + list.add(m1); + list.add(m1); + new IntegerMapGenotype(list, lower, upper); + } + @Test(expected = IllegalArgumentException.class) public void testGetIndexInvalidKey() { int[] lowerBounds = { 1, 2, 3 }; @@ -188,7 +211,7 @@ public void testToString() { IntegerMapGenotype integerMapGenotype = new IntegerMapGenotype( inputList, bounds); integerMapGenotype.init(rand); - assertEquals("[mock=1.0;mock=2.0;mock=3.0;]", integerMapGenotype.toString()); + assertEquals("[mock=1;mock=2;mock=3;]", integerMapGenotype.toString()); } @Test