// BLXAlphaCrossover.java
//
// Author:
// Antonio J. Nebro <antonio@lcc.uma.es>
//
// Copyright (c) 2012 Antonio J. Nebro
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package jmetal.operators.crossover;
import jmetal.core.Solution;
import jmetal.encodings.solutionType.ArrayRealSolutionType;
import jmetal.encodings.solutionType.RealSolutionType;
import jmetal.util.Configuration;
import jmetal.util.JMException;
import jmetal.util.PseudoRandom;
import jmetal.util.wrapper.XReal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
/**
* This class allows to apply a SBX crossover operator using two parent
* solutions.
*/
public class BLXAlphaCrossover extends Crossover {
/**
* EPS defines the minimum difference allowed between real values
*/
private static final double DEFAULT_ALPHA = 0.5;
private double alpha_ = DEFAULT_ALPHA ;
private Double crossoverProbability_ = null;
/**
* Valid solution types to apply this operator
*/
private static final List VALID_TYPES = Arrays.asList(RealSolutionType.class,
ArrayRealSolutionType.class) ;
/**
* Constructor
* Create a new SBX crossover operator whit a default
* index given by <code>DEFAULT_INDEX_CROSSOVER</code>
*/
public BLXAlphaCrossover(HashMap<String, Object> parameters) {
super (parameters) ;
if (parameters.get("probability") != null)
crossoverProbability_ = (Double) parameters.get("probability") ;
if (parameters.get("alpha") != null)
alpha_ = (Double) parameters.get("alpha") ;
} // SBXCrossover
/**
* Perform the crossover operation.
* @param probability Crossover probability
* @param parent1 The first parent
* @param parent2 The second parent
* @return An array containing the two offsprings
*/
public Solution[] doCrossover(double probability,
Solution parent1,
Solution parent2) throws JMException {
Solution [] offSpring = new Solution[2];
offSpring[0] = new Solution(parent1);
offSpring[1] = new Solution(parent2);
int i;
double random;
double valueY1 ;
double valueY2 ;
double valueX1 ;
double valueX2 ;
double upperValue ;
double lowerValue ;
XReal x1 = new XReal(parent1) ;
XReal x2 = new XReal(parent2) ;
XReal offs1 = new XReal(offSpring[0]) ;
XReal offs2 = new XReal(offSpring[1]) ;
int numberOfVariables = x1.getNumberOfDecisionVariables() ;
if (PseudoRandom.randDouble() <= probability){
for (i=0; i<numberOfVariables; i++){
upperValue = x1.getUpperBound(i);
lowerValue = x1.getLowerBound(i);
valueX1 = x1.getValue(i) ;
valueX2 = x2.getValue(i) ;
double max ;
double min ;
double range ;
if (valueX2 > valueX1) {
max = valueX2 ;
min = valueX1 ;
} // if
else {
max = valueX1 ;
min = valueX2 ;
} // else
range = max - min ;
// Ranges of the new alleles ;
double minRange ;
double maxRange ;
minRange = min - range*alpha_;
maxRange = max + range*alpha_;
random = PseudoRandom.randDouble();
valueY1 = minRange + random * (maxRange - minRange) ;
random = PseudoRandom.randDouble() ;
valueY2 = minRange + random * (maxRange - minRange) ;
if (valueY1 < lowerValue)
offs1.setValue(i, lowerValue) ;
else if (valueY1 > upperValue)
offs1.setValue(i, upperValue);
else
offs1.setValue(i, valueY1);
if (valueY2 < lowerValue)
offs2.setValue(i, lowerValue) ;
else if (valueY2 > upperValue)
offs2.setValue(i, upperValue) ;
else
offs2.setValue(i, valueY2) ;
} // if
} // if
return offSpring;
} // doCrossover
/**
* Executes the operation
* @param object An object containing an array of two parents
* @return An object containing the offSprings
*/
public Object execute(Object object) throws JMException {
Solution [] parents = (Solution [])object;
if (parents.length != 2) {
Configuration.logger_.severe("BLXAlphaCrossover.execute: operator needs two " +
"parents");
Class cls = java.lang.String.class;
String name = cls.getName();
throw new JMException("Exception in " + name + ".execute()") ;
} // if
if (!(VALID_TYPES.contains(parents[0].getType().getClass()) &&
VALID_TYPES.contains(parents[1].getType().getClass())) ) {
Configuration.logger_.severe("BLXAlphaCrossover.execute: the solutions " +
"type " + parents[0].getType() + " is not allowed with this operator");
Class cls = java.lang.String.class;
String name = cls.getName();
throw new JMException("Exception in " + name + ".execute()") ;
} // if
Solution [] offSpring;
offSpring = doCrossover(crossoverProbability_,
parents[0],
parents[1]);
return offSpring;
} // execute
} // BLXAlphaCrossover