/*
* Copyright 2015 S. Webber
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.oakgp.primitive;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.oakgp.TestUtils.assertConstant;
import static org.oakgp.TestUtils.assertVariable;
import static org.oakgp.TestUtils.createVariable;
import static org.oakgp.TestUtils.integerConstant;
import static org.oakgp.Type.booleanType;
import static org.oakgp.Type.integerType;
import static org.oakgp.Type.stringType;
import static org.oakgp.util.Utils.createIntegerTypeArray;
import org.junit.Test;
import org.oakgp.Type;
import org.oakgp.function.Function;
import org.oakgp.function.choice.If;
import org.oakgp.function.compare.Equal;
import org.oakgp.function.compare.GreaterThan;
import org.oakgp.function.compare.GreaterThanOrEqual;
import org.oakgp.function.compare.LessThan;
import org.oakgp.function.compare.LessThanOrEqual;
import org.oakgp.function.compare.NotEqual;
import org.oakgp.function.math.IntegerUtils;
import org.oakgp.node.ConstantNode;
import org.oakgp.node.VariableNode;
import org.oakgp.util.DummyRandom;
import org.oakgp.util.Random;
public class PrimitiveSetImplTest {
// TODO add extra tests for when: a) numVariables=0, b) numVariables=1 and c) constants.length=0
private static final double VARIABLE_RATIO = .6;
private static final ConstantNode[] CONSTANTS = { integerConstant(7), integerConstant(8), integerConstant(9) };
private static final Type[] VARIABLE_TYPES = createIntegerTypeArray(3);
private static final Function[] FUNCTIONS = new Function[] { IntegerUtils.INTEGER_UTILS.getAdd(), IntegerUtils.INTEGER_UTILS.getSubtract(),
IntegerUtils.INTEGER_UTILS.getMultiply(), new If(integerType()), LessThan.create(integerType()), LessThanOrEqual.create(integerType()),
new GreaterThan(integerType()), new GreaterThanOrEqual(integerType()), new Equal(integerType()), new NotEqual(integerType()) };
@Test
public void testHasFunctions() {
PrimitiveSet p = createWithFunctions(DummyRandom.EMPTY);
assertTrue(p.hasFunctions(integerType()));
assertFalse(p.hasFunctions(stringType()));
}
@Test
public void testHasTerminals() {
PrimitiveSet p = createWithTerminals(DummyRandom.EMPTY);
assertTrue(p.hasTerminals(integerType()));
assertFalse(p.hasTerminals(stringType()));
}
@Test
public void testNextFunction() {
Random mockRandom = mock(Random.class);
// mock randomly selecting one of the 4 functions in OPERATORS with an integer return type
given(mockRandom.nextInt(4)).willReturn(1, 0, 2, 1, 2, 0, 3);
// mock randomly selecting one of the 6 functions in OPERATORS with a boolean return type
given(mockRandom.nextInt(6)).willReturn(1, 0, 5, 4);
PrimitiveSet functionSet = createWithFunctions(mockRandom);
// TODO test with more than just integerType()
assertSame(FUNCTIONS[1], functionSet.nextFunction(integerType()));
assertSame(FUNCTIONS[0], functionSet.nextFunction(integerType()));
assertSame(FUNCTIONS[2], functionSet.nextFunction(integerType()));
assertSame(FUNCTIONS[1], functionSet.nextFunction(integerType()));
assertSame(FUNCTIONS[2], functionSet.nextFunction(integerType()));
assertSame(FUNCTIONS[0], functionSet.nextFunction(integerType()));
assertSame(FUNCTIONS[3], functionSet.nextFunction(integerType()));
assertSame(FUNCTIONS[5], functionSet.nextFunction(booleanType()));
assertSame(FUNCTIONS[4], functionSet.nextFunction(booleanType()));
assertSame(FUNCTIONS[9], functionSet.nextFunction(booleanType()));
assertSame(FUNCTIONS[8], functionSet.nextFunction(booleanType()));
}
@Test
public void testNextAlternativeFunction() {
Random mockRandom = mock(Random.class);
PrimitiveSet functionSet = createWithFunctions(mockRandom);
given(mockRandom.nextInt(3)).willReturn(0, 1, 2, 0);
given(mockRandom.nextInt(2)).willReturn(0, 1);
assertSame(FUNCTIONS[1], functionSet.nextAlternativeFunction(FUNCTIONS[0]));
assertSame(FUNCTIONS[1], functionSet.nextAlternativeFunction(FUNCTIONS[0]));
assertSame(FUNCTIONS[2], functionSet.nextAlternativeFunction(FUNCTIONS[0]));
assertSame(FUNCTIONS[2], functionSet.nextAlternativeFunction(FUNCTIONS[0]));
given(mockRandom.nextInt(3)).willReturn(0, 1, 1, 2);
given(mockRandom.nextInt(2)).willReturn(0, 1);
assertSame(FUNCTIONS[0], functionSet.nextAlternativeFunction(FUNCTIONS[1]));
assertSame(FUNCTIONS[0], functionSet.nextAlternativeFunction(FUNCTIONS[1]));
assertSame(FUNCTIONS[2], functionSet.nextAlternativeFunction(FUNCTIONS[1]));
assertSame(FUNCTIONS[2], functionSet.nextAlternativeFunction(FUNCTIONS[1]));
given(mockRandom.nextInt(3)).willReturn(0, 1, 2, 2);
given(mockRandom.nextInt(2)).willReturn(0, 1);
assertSame(FUNCTIONS[0], functionSet.nextAlternativeFunction(FUNCTIONS[2]));
assertSame(FUNCTIONS[1], functionSet.nextAlternativeFunction(FUNCTIONS[2]));
assertSame(FUNCTIONS[0], functionSet.nextAlternativeFunction(FUNCTIONS[2]));
assertSame(FUNCTIONS[1], functionSet.nextAlternativeFunction(FUNCTIONS[2]));
}
@Test
public void testNextTerminal() {
Random mockRandom = mock(Random.class);
given(mockRandom.nextDouble()).willReturn(0.0, VARIABLE_RATIO, VARIABLE_RATIO + .01, .9, VARIABLE_RATIO - .01, .7);
given(mockRandom.nextInt(3)).willReturn(1, 0, 2, 1, 0, 2);
PrimitiveSet terminalSet = createWithTerminals(mockRandom);
// TODO test with more than just integerType()
assertVariable(1, terminalSet.nextTerminal(integerType()));
assertConstant(7, terminalSet.nextTerminal(integerType()));
assertConstant(9, terminalSet.nextTerminal(integerType()));
assertConstant(8, terminalSet.nextTerminal(integerType()));
assertVariable(0, terminalSet.nextTerminal(integerType()));
assertConstant(9, terminalSet.nextTerminal(integerType()));
}
@Test
public void testNextAlternativeConstant() {
Random mockRandom = mock(Random.class);
given(mockRandom.nextDouble()).willReturn(VARIABLE_RATIO); // this will force constants to be produced
PrimitiveSet terminalSet = createWithTerminals(mockRandom);
given(mockRandom.nextInt(3)).willReturn(0, 1, 2, 0);
given(mockRandom.nextInt(2)).willReturn(0, 1);
assertConstant(8, terminalSet.nextAlternativeTerminal(CONSTANTS[0]));
assertConstant(8, terminalSet.nextAlternativeTerminal(CONSTANTS[0]));
assertConstant(9, terminalSet.nextAlternativeTerminal(CONSTANTS[0]));
assertConstant(9, terminalSet.nextAlternativeTerminal(CONSTANTS[0]));
given(mockRandom.nextInt(3)).willReturn(0, 1, 1, 2);
given(mockRandom.nextInt(2)).willReturn(0, 1);
assertConstant(7, terminalSet.nextAlternativeTerminal(CONSTANTS[1]));
assertConstant(7, terminalSet.nextAlternativeTerminal(CONSTANTS[1]));
assertConstant(9, terminalSet.nextAlternativeTerminal(CONSTANTS[1]));
assertConstant(9, terminalSet.nextAlternativeTerminal(CONSTANTS[1]));
given(mockRandom.nextInt(3)).willReturn(0, 1, 2, 2);
given(mockRandom.nextInt(2)).willReturn(0, 1);
assertConstant(7, terminalSet.nextAlternativeTerminal(CONSTANTS[2]));
assertConstant(8, terminalSet.nextAlternativeTerminal(CONSTANTS[2]));
assertConstant(7, terminalSet.nextAlternativeTerminal(CONSTANTS[2]));
assertConstant(8, terminalSet.nextAlternativeTerminal(CONSTANTS[2]));
given(mockRandom.nextInt(3)).willReturn(2, 0, 1);
assertConstant(9, terminalSet.nextAlternativeTerminal(createVariable(9)));
assertConstant(7, terminalSet.nextAlternativeTerminal(createVariable(9)));
assertConstant(8, terminalSet.nextAlternativeTerminal(createVariable(9)));
}
@Test
public void testNextAlternativeVariable() {
Random mockRandom = mock(Random.class);
given(mockRandom.nextDouble()).willReturn(VARIABLE_RATIO - .01); // this will force variables to be produced
ConstantSet constantSet = new ConstantSet(CONSTANTS);
VariableSet variableSet = VariableSet.createVariableSet(VARIABLE_TYPES);
PrimitiveSet terminalSet = new PrimitiveSetImpl(null, constantSet, variableSet, mockRandom, VARIABLE_RATIO);
given(mockRandom.nextInt(3)).willReturn(0, 1, 2, 0);
given(mockRandom.nextInt(2)).willReturn(0, 1);
VariableNode firstVariable = variableSet.getById(0);
assertVariable(1, terminalSet.nextAlternativeTerminal(firstVariable));
assertVariable(1, terminalSet.nextAlternativeTerminal(firstVariable));
assertVariable(2, terminalSet.nextAlternativeTerminal(firstVariable));
assertVariable(2, terminalSet.nextAlternativeTerminal(firstVariable));
given(mockRandom.nextInt(3)).willReturn(0, 1, 1, 2);
given(mockRandom.nextInt(2)).willReturn(0, 1);
VariableNode secondVariable = variableSet.getById(1);
assertVariable(0, terminalSet.nextAlternativeTerminal(secondVariable));
assertVariable(0, terminalSet.nextAlternativeTerminal(secondVariable));
assertVariable(2, terminalSet.nextAlternativeTerminal(secondVariable));
assertVariable(2, terminalSet.nextAlternativeTerminal(secondVariable));
given(mockRandom.nextInt(3)).willReturn(0, 1, 2, 2);
given(mockRandom.nextInt(2)).willReturn(0, 1);
VariableNode thirdVariable = variableSet.getById(2);
assertVariable(0, terminalSet.nextAlternativeTerminal(thirdVariable));
assertVariable(1, terminalSet.nextAlternativeTerminal(thirdVariable));
assertVariable(0, terminalSet.nextAlternativeTerminal(thirdVariable));
assertVariable(1, terminalSet.nextAlternativeTerminal(thirdVariable));
given(mockRandom.nextInt(3)).willReturn(2, 0, 1);
ConstantNode constantNode = integerConstant(9);
assertVariable(2, terminalSet.nextAlternativeTerminal(constantNode));
assertVariable(0, terminalSet.nextAlternativeTerminal(constantNode));
assertVariable(1, terminalSet.nextAlternativeTerminal(constantNode));
}
private PrimitiveSet createWithTerminals(Random random) {
ConstantSet constantSet = new ConstantSet(CONSTANTS);
VariableSet variableSet = VariableSet.createVariableSet(VARIABLE_TYPES);
return new PrimitiveSetImpl(null, constantSet, variableSet, random, VARIABLE_RATIO);
}
private PrimitiveSet createWithFunctions(Random random) {
return new PrimitiveSetImpl(new FunctionSet(FUNCTIONS), null, null, random, .1);
}
}