/**********************************************************************
# 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: Stiener Hub Location</p>
 * <p>Description: Finds Best Central Hub Location Given Facilities Randomly Placed
 * (x = -1 to 1, y = -1 to 1) with weight evenly spread across [1, 3]. Solution Granularity .01</p>
 * <p>Copyright: EWASystems Copyright (c) 1998 - 2005</p>
 * <p>Company: EWASystems</p>
 * @author Lincoln Evans-Beauchamp
 * @version 1.0
 */
public class StienerHubLocation extends GeneticProblem
{
  /** Facility Data */
  protected double[][] facilityData;

  /**
   * Problem Constructor
   */
  public StienerHubLocation()
  {
    super("Stiener Hub Location", "Finds Best Central Hub Location Given Facilities Randomly Placed (-1<x<1, -1<y<1) with weight evenly spread across [1, 3]");

    facilityData = new double[10][3];
    for (int i=0; i<facilityData.length; i++)
    {
      facilityData[i][0] = -1d + 2d*Math.random();
      facilityData[i][1] = -1d + 2d*Math.random();
      facilityData[i][2] = 1d+2d*Math.random();
    }
  }

  /**
   * The Objective Function
   * @param gene The Genetic Gene to Test
   * @return double: The Genetic Gene's Fitness
   */
  public double f(GeneticGene gene)
  {
    double x = ((Double)gene.getGeneValue(0)).doubleValue();
    double y = ((Double)gene.getGeneValue(1)).doubleValue();
    double fitness = 0d;
    for (int i=0; i<gene.getGeneLength(); i++)
    {
      double dist = Math.pow(facilityData[i][0] - x, 2d) + Math.pow(facilityData[i][1] - y, 2d);
      fitness += facilityData[i][2]*Math.sqrt(dist);
    }
    return fitness;
  }

  /**
   * 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(-1d), new Double(.01d), new Double(1d)};
    gas.addContinuousAllele("Double [-1, 1] by .01", values, 2);
    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 StienerHubLocation());
    grt.getConfig().setMaxGenerations(1000);
    grt.getConfig().setShowFinalReport(true);
    grt.run();
  }
}


