/** Start the background thread. */
  public void start() {
    // create a random list of cities

    cities = new City[TravelingSalesman.CITY_COUNT];
    for (int i = 0; i < TravelingSalesman.CITY_COUNT; i++) {
      cities[i] =
          new City(
              (int) (Math.random() * (getBounds().width - 10)),
              (int) (Math.random() * (getBounds().height - 60)));
    }

    // create the initial chromosomes

    chromosomes = new Chromosome[TravelingSalesman.POPULATION_SIZE];
    for (int i = 0; i < TravelingSalesman.POPULATION_SIZE; i++) {
      chromosomes[i] = new Chromosome(cities);
      chromosomes[i].setCut(cutLength);
      chromosomes[i].setMutation(TravelingSalesman.MUTATION_PERCENT);
    }
    Chromosome.sortChromosomes(chromosomes, TravelingSalesman.POPULATION_SIZE);

    // start up the background thread
    started = true;
    map.update(map.getGraphics());

    generation = 0;

    if (worker != null) worker = null;
    worker = new Thread(this);
    // worker.setPriority(Thread.MIN_PRIORITY);
    worker.start();
  }
  /** Start the background thread. */
  public void start() {
    // create a random list of cities

    cities = new City[TravelingSalesman.CITY_COUNT];
    for (int i = 0; i < TravelingSalesman.CITY_COUNT; i++) {
      cities[i] =
          new City(
              (int) (Math.random() * (getBounds().width - 10)),
              (int) (Math.random() * (getBounds().height - 60)));
    }

    // start up the background thread
    started = true;
    map.update(map.getGraphics());

    if (worker != null) worker = null;
    worker = new SimulateAnnealing(this);
    worker.setPriority(Thread.MIN_PRIORITY);
    worker.start();
  }
  /** The main loop for the background thread. It is here that most of the work os orchestrated. */
  public void run() {

    double thisCost = 500.0;
    double oldCost = 0.0;
    double dcost = 500.0;
    int countSame = 0;

    map.update(map.getGraphics());

    while (countSame < 100) {

      generation++;

      int ioffset = matingPopulationSize;
      int mutated = 0;

      // Mate the chromosomes in the favoured population
      // with all in the mating population
      for (int i = 0; i < favoredPopulationSize; i++) {
        Chromosome cmother = chromosomes[i];
        // Select partner from the mating population
        int father = (int) (0.999999 * Math.random() * (double) matingPopulationSize);
        Chromosome cfather = chromosomes[father];

        mutated += cmother.mate(cfather, chromosomes[ioffset], chromosomes[ioffset + 1]);
        ioffset += 2;
      }

      // The new generation is in the matingPopulation area
      // move them to the correct area for sort.
      for (int i = 0; i < matingPopulationSize; i++) {
        chromosomes[i] = chromosomes[i + matingPopulationSize];
        chromosomes[i].calculateCost(cities);
      }

      // Now sort the new mating population
      Chromosome.sortChromosomes(chromosomes, matingPopulationSize);

      double cost = chromosomes[0].getCost();
      dcost = Math.abs(cost - thisCost);
      thisCost = cost;
      double mutationRate = 100.0 * (double) mutated / (double) matingPopulationSize;

      NumberFormat nf = NumberFormat.getInstance();
      nf.setMinimumFractionDigits(2);
      nf.setMinimumFractionDigits(2);

      status.setText(
          "Generation "
              + generation
              + " Cost "
              + (int) thisCost
              + " Mutated "
              + nf.format(mutationRate)
              + "%");

      if ((int) thisCost == (int) oldCost) {
        countSame++;
      } else {
        countSame = 0;
        oldCost = thisCost;
      }
      map.update(map.getGraphics());
    }
    status.setText("Solution found after " + generation + " generations.");
  }