/**********************************************************************
# Copyright (c) EWA Systems Inc. 1998 - 2005 All Rights Reserved
#               No part of this program may be photocopied, reproduced,
#               or translated to another programming language without
#               the prior written consent of EWA Systems.
**********************************************************************/

package com.ewasystems.opt.ga.test;

import com.ewasystems.opt.ga.GeneticAlleleSet;
import com.ewasystems.opt.ga.GeneticEngine;
import com.ewasystems.opt.ga.GeneticGene;
import com.ewasystems.opt.ga.GeneticProblem;
import com.ewasystems.opt.ga.GeneticRunTask;

/**
 * <p>Genetic Algorithm Test Case: Rastrigin Function</p>
 * <p>Description: Minimize f(x) = 10.0*n + sum(x(i)^2 - 10.0*cos(2*Pi*x(i))) where X = [-600, 600] by .02</p>
 * <p>Copyright: EWASystems Copyright (c) 1998 - 2005</p>
 * <p>Company: EWASystems</p>
 * @author Lincoln Evans-Beauchamp
 * @version 1.0
 */
public class Rastrigin extends GeneticProblem
{
  /**
   * Problem Constructor
   */
  public Rastrigin()
  {
    super("Rastrigin Function", "Minimize f(x) = 10.0*n + sum(x(i)^2 - 10.0*cos(2*Pi*x(i))) where X = [-5.12, 5.12] by .0005");
  }

  /**
   * The Objective Function
   * @param gene The Genetic Gene to Test
   * @return double: The Genetic Gene's Fitness
   */
  public double f(GeneticGene gene)
  {
    double f1 = 0d;
    for (int i=0; i<gene.getGeneLength(); i++)
    {
      double x = ((Double)gene.getGeneValue(i)).doubleValue();
      f1 += x*x - 10d*Math.cos(2d*Math.PI*x);
    }
    return 100d + f1;
  }

  /**
   * Gets the Allele Set for the Problem
   * @return GeneticAlleleSet: The Allele Set
   */
  public GeneticAlleleSet getAlleleSet()
  {
    GeneticAlleleSet gas = new GeneticAlleleSet();
    Double[] values = new Double[] {new Double(-5.12d), new Double(.0005d), new Double(5.12d)};
    gas.addContinuousAllele("Double [-5.12, 5.12] by .0005", values, 10);
    return gas;
  }

  /**
   * Gets the Objective Type
   * @return int: The Objective Type
   */
  public int getObjectiveType()
    {return OBJECTIVE_TYPE_MIN;}

  /**
   * Main for Running the Problem
   * @param args Not Used
   */
  public static final void main(String[] args)
  {
    GeneticEngine ge = new GeneticEngine();
    GeneticRunTask grt = ge.createGeneticTask(new Rastrigin());
    grt.getConfig().setShowGenerationResults(true);
    grt.getConfig().setShowFinalReport(true);
    grt.getConfig().setMaxGenerations(50000);
    grt.getConfig().setStagnationLimit(20000);
    grt.run();
    System.out.println("Solution Gene: Fitness = "+grt.getResultGeneFitness());
    for (int i=0; i<grt.getResultGeneLength(); i++)
      {System.out.println("X"+i+": "+grt.getResultGeneValue(i));}
  }
}

/*
Value: -88.723 with 192 generations and 4663 Calls

Parameter #0   Value: -0.850
Parameter #1   Value: -0.750
Parameter #2   Value: -0.950
Parameter #3   Value: -0.900
Parameter #4   Value: -0.850
Parameter #5   Value: -0.950
Parameter #6   Value: -0.850
Parameter #7   Value: -0.850
Parameter #8   Value: -0.850
*/

