All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bnd.math.business.evo.EvoCompositeChromManipulatorBO Maven / Gradle / Ivy

The newest version!
package com.bnd.math.business.evo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import com.bnd.core.domain.ValueBound;
import com.bnd.core.reflection.ReflectionProvider;
import com.bnd.core.reflection.ReflectionUtil;
import com.bnd.core.util.RandomUtil;

import com.bnd.math.BndMathException;
import com.bnd.math.domain.evo.BitMutationType;
import com.bnd.math.domain.evo.CompositeChromosome;


public abstract class EvoCompositeChromManipulatorBO, C, E> extends EvoChromManipulatorBO {

	protected final Class[] elementClasses;
	protected final ValueBound[] codeElementValueBounds; 

	public EvoCompositeChromManipulatorBO(
		ReflectionProvider chromosomeRF,
		int codeSize,
		BitMutationType bitMutationType,
		Double pertrubMutationStrength,
		Class[] elementClasses,
		ValueBound[] codeElementValueBounds
	) {
		super(chromosomeRF, codeSize, bitMutationType, pertrubMutationStrength);
// 		TODO: This should work in JDK 1.7
//		this.elementClass = (Class) replicator.getParamClass(getClass(), 2);
		this.elementClasses = elementClasses;
		this.codeElementValueBounds = codeElementValueBounds;
	}

	public EvoCompositeChromManipulatorBO(
		ReflectionProvider chromosomeRF,
		int codeSize,
		BitMutationType bitMutationType,
		Double pertrubMutationStrength,
		Class sharedElementClass,
		ValueBound[] codeElementValueBounds
	) {
		this(chromosomeRF, codeSize, bitMutationType, pertrubMutationStrength, ReflectionUtil.fillNewArray(sharedElementClass, codeSize), codeElementValueBounds);
	}

	public EvoCompositeChromManipulatorBO(
		ReflectionProvider chromosomeRF,
		int codeSize,
		BitMutationType bitMutationType,
		Double pertrubMutationStrength,
		Class elementClass
	) {
		this(chromosomeRF, codeSize, bitMutationType, pertrubMutationStrength, elementClass, (ValueBound[]) null);
	}

	public EvoCompositeChromManipulatorBO(
		ReflectionProvider chromosomeRF,
		int codeSize,
		BitMutationType bitMutationType,
		Double pertrubMutationStrength,
		Class elementClass,
		ValueBound sharedCodeElementValueBound
	) {
		this(chromosomeRF, codeSize, bitMutationType, pertrubMutationStrength, elementClass, ReflectionUtil.fillNewArray(sharedCodeElementValueBound, codeSize));
	}

	@Override
	public Collection crossOverSplit(H parent1, H parent2, int position) {
		final int codeSize = parent1.getCodeSize();
		H offspring1 = createNewChromosome();
		H offspring2 = createNewChromosome();
		for (int elementIndex = 0; elementIndex < codeSize; elementIndex++) {
			if (elementIndex == position) {
				H tempParent = parent1;
				parent1 = parent2;
				parent2 = tempParent;
			}
			offspring1.copyCodeAt(elementIndex, parent1);
			offspring2.copyCodeAt(elementIndex, parent2);
		}
		Collection offsprings = new ArrayList();
		offsprings.add(offspring1);
		offsprings.add(offspring2);
		return offsprings;
	}

	@Override
	public Collection crossOverShuffle(H parent1, H parent2, int firstParentPositionNum) {
		final int codeSize = parent1.getCodeSize();
		H offspring1 = createNewChromosome();
		H offspring2 = createNewChromosome();
		Collection firstParentPositions = RandomUtil.nextElementsWithoutRepetitions(codeSize, firstParentPositionNum);
		for (int elementIndex = 0; elementIndex < codeSize; elementIndex++) {
			if (firstParentPositions.contains(elementIndex)) {
				offspring1.copyCodeAt(elementIndex, parent1);
				offspring2.copyCodeAt(elementIndex, parent2);
			} else {
				offspring1.copyCodeAt(elementIndex, parent2);
				offspring2.copyCodeAt(elementIndex, parent1);				
			}
		}
		Collection offsprings = new ArrayList();
		offsprings.add(offspring1);
		offsprings.add(offspring2);
		return offsprings;
	}

	@Override
	public H generateRandomChromosome() {
		H newChromosome = createNewChromosome();
		for (int i = 0; i < codeSize; i++) {
			newChromosome.setCodeAt(i, generateRandomCodeElement(i));
		}
		return newChromosome;
	}

	protected E generateRandomCodeElement(int index) {
		return RandomUtil.next(elementClasses[index], codeElementValueBounds != null ? codeElementValueBounds[index] : null);
	}

	protected E generatePerturbatedElement(E value, ValueBound codeElementValueBound, Double strength) {
		if (codeElementValueBound == null) {
			throw new BndMathException("No code element value bound defined, but expected.");
		}
		E perturbatedElementValue = null;
		if (codeElementValueBound.hasEnumeratedValues()) {
			int enumIndex = codeElementValueBound.getEnumeratedValueIndex(value);
			int newIndex = RandomUtil.perturbate(enumIndex, strength, 0, codeElementValueBound.getEnumeratedOrderedValuesNum() - 1);
			perturbatedElementValue = codeElementValueBound.getEnumeratedOrderedValues()[newIndex];
		} else {
			// assume code element is a number
			ValueBound numberCodeElementValueBound = (ValueBound) codeElementValueBound;
			perturbatedElementValue = (E) RandomUtil.perturbate((Number) value, strength, numberCodeElementValueBound.getFrom(), numberCodeElementValueBound.getTo());
		}
		return perturbatedElementValue;
	}

	@Override
	public void mutateOneBit(H chromosome) {
		int codeIndex = RandomUtil.nextInt(codeSize);
		mutateElement(chromosome, codeIndex);
	}

	@Override
	public void mutateTwoBits(H chromosome) {
		mutateElements(chromosome, 2);
	}

	@Override
	public void mutateBySwapping(H chromosome) {
		int index1 = RandomUtil.nextInt(codeSize);
		int index2 = RandomUtil.nextIntExcept(codeSize, index1); 
		chromosome.swapElements(index1, index2);		
	}

	@Override
	public void mutatePerBit(H chromosome, double mutationPerBitProbability) {
		for (int i = 0; i < codeSize; i ++) {
			if (RandomUtil.nextDouble() < mutationPerBitProbability) {
				mutateElement(chromosome, i);
			}
		}
	}

	protected void mutateElement(H chromosome, int pos) {
		E mutatedElement = null;
		switch (bitMutationType) {
			case Replacement:
				mutatedElement = generateRandomCodeElement(pos);
				break;
			case Perturbation:
				mutatedElement = generatePerturbatedElement(chromosome.getCodeAt(pos), codeElementValueBounds[pos], pertrubMutationStrength);
				break;
		}
		chromosome.setCodeAt(pos, mutatedElement);
	}

	/**
	 * Mutates the given number of elements in chromosome code.
	 *
	 * @param elementsNum The number of elements to mutate.
	 */
	public void mutateElements(H chromosome, int elementsNum) {
		List availableIndeces = new ArrayList();
		for (int i = 0; i < codeSize; i++) {
			availableIndeces.add(new Integer(i));
		}
		Collections.shuffle(availableIndeces);
		for (int i = 0; i < elementsNum; i++) {
			int selectedElementIndex = availableIndeces.remove(0);
			mutateElement(chromosome, selectedElementIndex);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy