gt: 					value = xCurrent.getValue(j);
context: //  DifferentialEvolutionCrossover.java
  //
  //  Author:
  //       Antonio J. Nebro <antonio@lcc.uma.es>
  //       Juan J. Durillo <durillo@lcc.uma.es>
  //
  //  Copyright (c) 2011 Antonio J. Nebro, Juan J. Durillo
  //
  //  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 java.util.Arrays;
  import java.util.HashMap;
  import java.util.List;
  
  import jmetal.core.Solution;
  import jmetal.encodings.solutionType.ArrayRealSolutionType;
  import jmetal.encodings.solutionType.RealSolutionType;
  import jmetal.operators.crossover.Crossover;
  import jmetal.util.Configuration;
  import jmetal.util.JMException;
  import jmetal.util.PseudoRandom;
  import jmetal.util.wrapper.XReal;
  
  /**
   * Differential evolution crossover operators
   * Comments:
   * - The operator receives two parameters: the current individual and an array
   *   of three parent individuals
   * - The best and rand variants depends on the third parent, according whether
   *   it represents the current of the "best" individual or a randon one. 
   *   The implementation of both variants are the same, due to that the parent 
   *   selection is external to the crossover operator. 
   * - Implemented variants:
   *   - rand/1/bin (best/1/bin)
   *   - rand/1/exp (best/1/exp)
   *   - current-to-rand/1 (current-to-best/1)
   *   - current-to-rand/1/bin (current-to-best/1/bin)
   *   - current-to-rand/1/exp (current-to-best/1/exp)
   */
  public class DifferentialEvolutionCrossover extends Crossover {
  	/**
  	 * 
  	 */
  	private static final long serialVersionUID = 1L;
  
  	/**
  	 * DEFAULT_CR defines a default CR (crossover operation control) value
  	 */
  	public static final double DEFAULT_CR = 0.5; 
  
  	/**
  	 * DEFAULT_F defines the default F (Scaling factor for mutation) value
  	 */
  	private static final double DEFAULT_F = 0.5;
  
  	/**
  	 * DEFAULT_K defines a default K value used in variants current-to-rand/1
  	 * and current-to-best/1
  	 */
  	public static final double DEFAULT_K = 0.5; 
  
  	/**
  	 * DEFAULT_VARIANT defines the default DE variant
  	 */
  
  	private static final String DEFAULT_DE_VARIANT = "rand/1/bin";
  
    /**
     * Valid solution types to apply this operator 
     */
    @SuppressWarnings({ "rawtypes" })
  private static List VALID_TYPES = Arrays.asList(RealSolutionType.class, 
    		                                            ArrayRealSolutionType.class) ;
  
  	public double CR_  ;
  	public double F_   ;
  	public double K_   ;
  	private String DE_Variant_ ; // DE variant (rand/1/bin, rand/1/exp, etc.)
  
  	/**
  	 * Constructor
  	 */
  	public DifferentialEvolutionCrossover(HashMap<String, Object> parameters, PseudoRandom pseudoRandom) {
  		super(parameters, pseudoRandom) ;
  		
  		CR_ = DEFAULT_CR ;
  		F_  = DEFAULT_F  ;
  		K_  = DEFAULT_K   ;
  		DE_Variant_ = DEFAULT_DE_VARIANT ;
  		
    	if (parameters.get("CR") != null)
    		CR_ = (Double) parameters.get("CR") ;  		
    	if (parameters.get("F") != null)
    		F_ = (Double) parameters.get("F") ;  		
    	if (parameters.get("K") != null)
    		K_ = (Double) parameters.get("K") ;  		
    	if (parameters.get("DE_VARIANT") != null)
    		DE_Variant_ = (String) parameters.get("DE_VARIANT") ;  		
  
  	} // Constructor
  
  
  	/**
  	 * Constructor
  	 */
  	//public DifferentialEvolutionCrossover(Properties properties) {
  	//	this();
  	//	CR_ = (new Double((String)properties.getProperty("CR_")));
  	//	F_  = (new Double((String)properties.getProperty("F_")));
  	//	K_  = (new Double((String)properties.getProperty("K_")));
  	//	DE_Variant_ = properties.getProperty("DE_Variant_") ;
  	//} // Constructor
  
  	/**
  	 * Executes the operation
  	 * @param object An object containing an array of three parents
  	 * @return An object containing the offSprings
  	 */
  	@SuppressWarnings("rawtypes")
  	@Override
  	public Object execute(Object object) throws JMException {
  		Object[] parameters = (Object[])object ;
  		Solution current   = (Solution) parameters[0];
  		Solution [] parent = (Solution [])parameters[1];
  
  		Solution child ;
  		
      if (!(VALID_TYPES.contains(parent[0].getType().getClass()) &&
            VALID_TYPES.contains(parent[1].getType().getClass()) &&
            VALID_TYPES.contains(parent[2].getType().getClass())) ) {
  
  			Configuration.logger_.severe("DifferentialEvolutionCrossover.execute: " +
  					" the solutions " +
  					"are not of the right type. The type should be 'Real' or 'ArrayReal', but " +
  					parent[0].getType() + " and " + 
  					parent[1].getType() + " and " + 
  					parent[2].getType() + " are obtained");
  
  			Class cls = java.lang.String.class;
  			String name = cls.getName(); 
  			throw new JMException("Exception in " + name + ".execute()") ;
  		}
  
  		int jrand ;
  
  		child = new Solution(current) ;
  		
  		XReal xParent0 = new XReal(parent[0]) ;
  		XReal xParent1 = new XReal(parent[1]) ;
  		XReal xParent2 = new XReal(parent[2]) ;
  		XReal xCurrent = new XReal(current) ;
  		XReal xChild   = new XReal(child) ;
  
  		int numberOfVariables = xParent0.getNumberOfDecisionVariables() ;
  		jrand = (int)(pseudoRandom.randInt(0, numberOfVariables - 1)) ;
  
  		// STEP 4. Checking the DE variant
  		if ((DE_Variant_.compareTo("rand/1/bin") == 0) || 
  				(DE_Variant_.compareTo("best/1/bin") == 0)) { 
  			for (int j=0; j < numberOfVariables; j++) {
  				if (pseudoRandom.randDouble(0, 1) < CR_ || j == jrand) {
  					double value ;
  					value = xParent2.getValue(j)  + F_ * (xParent0.getValue(j) -
  							                                  xParent1.getValue(j)) ;
  					
  					if (value < xChild.getLowerBound(j))
  						value =  xChild.getLowerBound(j) ;
  					if (value > xChild.getUpperBound(j))
  						value = xChild.getUpperBound(j) ;
            /*
  					if (value < xChild.getLowerBound(j)) {
              double rnd = PseudoRandom.randDouble(0, 1) ;
              value = xChild.getLowerBound(j) + rnd *(xParent2.getValue(j) - xChild.getLowerBound(j)) ;
  					}
            if (value > xChild.getUpperBound(j)) {
              double rnd = PseudoRandom.randDouble(0, 1) ;
              value = xChild.getUpperBound(j) - rnd*(xChild.getUpperBound(j)-xParent2.getValue(j)) ;
            }
            */
  					xChild.setValue(j, value) ;
  				}
  				else {
  					double value ;
  					value = xCurrent.getValue(j);
  					xChild.setValue(j, value) ;
  				} // else
  			} // for
  		} // if
  		else if ((DE_Variant_.compareTo("rand/1/exp") == 0) || 
  				(DE_Variant_.compareTo("best/1/exp") == 0)) {
  			for (int j=0; j < numberOfVariables; j++) {
  				if (pseudoRandom.randDouble(0, 1) < CR_ || j == jrand) {
  					double value ;
  					value = xParent2.getValue(j)  + F_ * (xParent0.getValue(j) -
  							xParent1.getValue(j)) ;
  
  					if (value < xChild.getLowerBound(j))
  						value =  xChild.getLowerBound(j) ;
  					if (value > xChild.getUpperBound(j))
  						value = xChild.getUpperBound(j) ;
  
  					xChild.setValue(j, value) ;
  				}
  				else {
  					CR_ = 0.0 ;
  					double value ;
  					value = xCurrent.getValue(j);
  					xChild.setValue(j, value) ;
  			  } // else
  			} // for		
  		} // if
  		else if ((DE_Variant_.compareTo("current-to-rand/1") == 0) || 
  				(DE_Variant_.compareTo("current-to-best/1") == 0)) { 
  			for (int j=0; j < numberOfVariables; j++) {
  				double value ;
  				value = xCurrent.getValue(j) + K_ * (xParent2.getValue(j) - 
  					    xCurrent.getValue(j)) +					
  						  F_ * (xParent0.getValue(j) - xParent1.getValue(j)) ;
  
  				if (value < xChild.getLowerBound(j))
  					value =  xChild.getLowerBound(j) ;
  				if (value > xChild.getUpperBound(j))
  					value = xChild.getUpperBound(j) ;
  
  				xChild.setValue(j, value) ;
  			} // for		
  		} // if
  		else if ((DE_Variant_.compareTo("current-to-rand/1/bin") == 0) ||
  				(DE_Variant_.compareTo("current-to-best/1/bin") == 0)) { 
  			for (int j=0; j < numberOfVariables; j++) {
  				if (pseudoRandom.randDouble(0, 1) < CR_ || j == jrand) {
  					double value ;
  					value = xCurrent.getValue(j) + K_ * (xParent2.getValue(j) - 
  							xCurrent.getValue(j)) +					
  							F_ * (xParent0.getValue(j) - xParent1.getValue(j)) ;
  
  					if (value < xChild.getLowerBound(j))
  						value =  xChild.getLowerBound(j) ;
  					if (value > xChild.getUpperBound(j))
  						value = xChild.getUpperBound(j) ;
  
  					xChild.setValue(j, value) ;
  				}
  				else {
  					double value ;
  