@Override
  protected double evaluation(IChromosome ic) {
    double result = 0.0;
    Gene[] genes = ic.getGenes();

    for (Gene g : genes) {
      Note[] chord = (Note[]) g.getAllele();
      int[] foundChord = HarmonicUtils.findChord(chord, tonic, scale);
      if (foundChord != null)
        if (HarmonicUtils.isFundamentalDuplicated(chord, foundChord))
          result += 1 / (genes.length * 1.0);
    }

    return result;
  }
  protected void doCrossover(
      IChromosome firstMate,
      IChromosome secondMate,
      List a_candidateChromosomes,
      RandomGenerator generator) {
    Gene[] firstGenes = firstMate.getGenes();
    Gene[] secondGenes = secondMate.getGenes();
    int locus = generator.nextInt(firstGenes.length);
    // Swap the genes.
    // ---------------
    Gene gene1, gene11;
    Gene gene2, gene22;
    Integer firstAllele, firstAllele1;
    Integer secondAllele, secondAllele1;

    for (int j = locus; j < firstGenes.length; j++) {
      gene1 = firstGenes[j];
      gene2 = secondGenes[j];

      firstAllele = (Integer) gene1.getAllele();
      secondAllele = (Integer) gene2.getAllele();

      if (payload[firstAllele] != null && payload[secondAllele] != null) {
        if (!checkAlleles(firstMate, j, secondAllele)) gene1.setAllele(secondAllele);
        if (!checkAlleles(secondMate, j, firstAllele)) gene2.setAllele(firstAllele);
      }

      if (payload[firstAllele] == null && payload[secondAllele] == null) {

        if (payload[64 + firstAllele].getPair() != payload[64 + secondAllele].getPair()) continue;

        if (payload[64 + firstAllele].getPair() == 1) {
          if (!checkAlleles(firstMate, j, secondAllele)
              && !checkAlleles(secondMate, j, firstAllele)) {
            if (chkonepair(j) || chktwopair(j + 1)) {
              System.out.println("Crossover.. something wrong");
            }

            gene11 = firstGenes[j + 1];
            firstAllele1 = (Integer) gene11.getAllele();

            gene22 = secondGenes[j + 1];
            secondAllele1 = (Integer) gene22.getAllele();

            if (!checkAlleles(firstMate, j + 1, secondAllele1)) {
              gene1.setAllele(secondAllele);
              gene11.setAllele(secondAllele1);
            }

            if (!checkAlleles(secondMate, j + 1, firstAllele1)) {
              gene2.setAllele(firstAllele);
              gene22.setAllele(firstAllele1);
            }
          }
        } else if (payload[64 + firstAllele].getPair() == 2) {

          if (!checkAlleles(firstMate, j, secondAllele)
              && !checkAlleles(secondMate, j, firstAllele)) {

            gene11 = firstGenes[j - 1];
            firstAllele1 = (Integer) gene11.getAllele();

            gene22 = secondGenes[j - 1];
            secondAllele1 = (Integer) gene22.getAllele();

            if (!checkAlleles(firstMate, j - 1, secondAllele1)) {
              gene1.setAllele(secondAllele);
              gene11.setAllele(secondAllele1);
            }

            if (!checkAlleles(secondMate, j - 1, firstAllele1)) {
              gene2.setAllele(firstAllele);
              gene22.setAllele(firstAllele1);
            }
          }
        } else {
          System.out.println("...Invalid Configuration Exception...");
        }
      }
    }
    // Add the modified chromosomes to the candidate pool so that
    // they'll be considered for natural selection during the next
    // phase of evolution.
    // -----------------------------------------------------------
    a_candidateChromosomes.add(firstMate);
    a_candidateChromosomes.add(secondMate);
  }